discuz任意文件删除漏洞复现

Discuz任意文件删除漏洞复现

0x00 概述

Discuz!X社区软件,是一个采用PHP和MySQL等其他多种数据库构建的性能优异、功能全面、安全稳定的社区论坛平台。但是任何代码都会因为不可避免的原因而存在着安全问题。这次的任意文件删除一是因为后台变量没有对前端传回的数据做校验,理论上下拉框只能传回框中的数据(选择框同理),传来什么就是什么。如果不是,那么肯定是被人改过,直接扔掉这个包并记录IP;二是因为Discuz的功能很全,有删除文件的功能,但是权限管理的不好。删除文件这种敏感的操作应该做一些限制。这里恰好删除文件的代码里面包含着可以被修改的数据,于是漏洞就产生了。

0x01 漏洞复现

环境:win10+phpstudy(php5.6)+discuz3.2(2.8-3.3都可以)

0x00、创建一个测试文件text.txt到网站根目录下

0x01、找到formhash的值

0x02、修改某一表单的值为测试文件的相对位置../../../text.txt

0x03、上传图片到上述表单的变量中(直接POST或者自己构造表单)

0x04、删除成功

img

进入自己的个人资料页面,找到出生地

img

用burp抓包直接改为../../../text.txt

img

找到formhash的值

img

构造上传文件的表单,上传图片

img

上传任意图片文件

img

查看网站目录, text.txt已经成功删除

img

0x02 漏洞原理

先看的官方补丁:之间删除了所有的unlike语句

img

倒着看,unlike用来删除文件:

  • @unlink(getglobal(‘setting/attachdir’).’./profile/’.$verifyinfo[‘field’][$key]);

  • 所以是向上三级目录../../../

  • 向上看,有一段判断文件是否上传成功的代码
1
2
3
4
5
6
7
8
9
10
if($_FILES) {
$upload = new discuz_upload();
foreach($_FILES as $key => $file){
if(!isset($_G[‘cache’][‘profilesetting’][$key])){
continue;
} /*这里是一些检查文件是否上传成功的代码,如果不成功会做相应的反应*/
@unlink(getglobal(‘setting/attachdir’).’./profile/’.$space[$key]);
$setarr[$key] = $attach[‘attachment’];
}
}
  • 看到space这个变量
  • 看看space_merge这个函数,是用来设置个人信息的
  • 于是在其中就找到一个变量,让其变成文件路径,上面复现的时候选的这个变量是出生地(birthprovince),之后你上传了一个文件后,就会执行@unlink(getglobal(.%E2%80%98./profile/%E2%80%99.$space%5b$key%5d))setting/attachdir.%E2%80%98./profile/%E2%80%99.$space%5b$key%5d)))..%E2%80%98./profile/%E2%80%99.$space%5b$key%5d)).%E2%80%98./profile/%E2%80%99.$space%5b$key%5d))./profile/.%E2%80%98./profile/%E2%80%99.$space%5b$key%5d)).$space[$key]);**
  • 而这个时候$space这个变量里是我们刚刚改的任意文件的路径,于是乎就删除了这个文件

0x03 写在最后

  • 代码功底十分重要,需要加强。
  • 漏洞复现一定要亲自搭环境去试试,不能光看别人做,在做的过程中会遇到很多想不到的问题,同时也能学到不少东西。
  • 多关注安全动态,目前最新的书上的东西也已经落后现在起码1-2年了
  • 一定要刨根问底,有的时候一些细节可能正是问题的关键。比如说这次的目录问题,为什么是向上三级,看了代码之后才彻底明白,这是个很关键的地方。
  • 官方的补丁直接把所有unlike语句全部删除了,虽然确实是不能删除文件了。但是理论上来说应该把前后端都做校验,删除文件的语句要检查权限。