8

Discuz v3.4 排行页面存储型XSS漏洞分析

 2 years ago
source link: https://chybeta.github.io/2018/10/15/Discuz-v3-4-%E6%8E%92%E8%A1%8C%E9%A1%B5%E9%9D%A2%E5%AD%98%E5%82%A8%E5%9E%8BXSS%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Discuz v3.4 排行页面存储型XSS漏洞分析

发表于 2018-10-15

| 分类于 Web Security

| 阅读次数

2018年10月12日,Discuz官方修复了一处XSS漏洞:

source/module/misc/misc_ranklist.php:166

<?php
function getranklist_members($offset = 0, $limit = 20) {
require_once libfile('function/forum');
$members = array();
$topusers = C::t('home_show')->fetch_all_by_unitprice($offset, $limit, true);
foreach($topusers as $member) {
$member['avatar'] = avatar($member['uid'], 'small');
$member['note'] = dhtmlspecialchars($member['note']);
$members[] = $member;
return $members;

Dz在此处获取到$member['note']后调用了dhtmlspecialchars进行过滤,在source/function/function_core.php:203 会对’&’, ‘“‘, ‘<’, ‘>’进行实体编码。

<?php
function dhtmlspecialchars($string, $flags = null) {
if(is_array($string)) {
} else {
if($flags === null) {
$string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string);
} else {
return $string;

getranklist_members返回后 source/include/misc/misc_ranklist_index.php:113

<?php
if($ranklist_setting['member']['available']) {
$memberlist = getranklist_members(0, 27);
include template('diy:ranklist/ranklist');

进行模板的渲染在 data/template/1_diy_ranklist_ranklist.tpl.php:32

<?php if($memberlist) { ?>
<a href="home.php?mod=space&uid=<?php echo $memberlist['0']['uid'];?>&do=profile" target="_blank" id="bid_<?php echo $memberlist['0']['uid'];?>" class="hm" <?php if($memberlist['0']['note']) { ?> onmouseover="showTip(trhis)" tip="<?php echo $memberlist['0']['username'];?>: <?php echo $memberlist['0']['note'];?>"<?php } ?>><?php echo avatar($memberlist[0][uid],middle);?></a>
<?php } ?>

可以看到在tip属性中输出了$memberlist['0']['note']。在之前有一个onmouseover事件,跟入showTip(trhis) 在 static/js/common.js:1062

function showTip(ctrlobj) {
$F('_showTip', arguments);

跟入_showTip,在 static/js/common_extra.js:912

function _showTip(ctrlobj) {
if(!ctrlobj.id) {
ctrlobj.id = 'tip_' + Math.random();
menuid = ctrlobj.id + '_menu';
if(!$(menuid)) {
var div = document.createElement('div');
div.id = ctrlobj.id + '_menu';
div.className = 'tip tip_4';
div.style.display = 'none';
div.innerHTML = '<div class="tip_horn"></div><div class="tip_c">' + ctrlobj.getAttribute('tip') + '</div>';
$('append_parent').appendChild(div);
$(ctrlobj.id).onmouseout = function () { hideMenu('', 'prompt'); };
showMenu({'mtype':'prompt','ctrlid':ctrlobj.id,'pos':'12!','duration':2,'zindex':JSMENU['zIndex']['prompt']});

通过ctrlobj.getAttribute('tip')获取tip属性的值,由于getAttribute获取的内容会自动反转义,即前面在dhtmlspecialchars编码过的内容又被解码了一次。此后拼接到div标签的innerHTML中,最后输出到页面上造成了xss

关于getAttribute,可以用下面代码测试:

<html>
<div name="<a>" id="div">test</div>
<script>
div1 = document.getElementById("div");
align = div1.getAttribute("name");
alert(align);
</script>

该CMS中,排行榜功能是默认开启的。在地址 http://127.0.0.1/misc.php?mod=ranklist&type=member 的上榜宣言中输入payload(拒绝伸手党)

http://127.0.0.1/misc.php?mod=ranklist 当鼠标移动到头像上触发onmouseover事件,执行xss

多增加一次dhtmlspecialchars

微信扫码加入知识星球【漏洞百出】

点击图片放大,扫码知识星球【漏洞百出】


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK