Discuz!(v3.4 及以下) 任意文件删除漏洞分析

Author Avatar
Tr0y 4月 26, 2018 15:46:59 本文共 1.3k 字
  • 文为知己者书
  • 在其它设备中阅读本文章

最近在做 CVE(或者说漏洞)的应急响应。原本应该是不看任何相关分析,仅凭漏洞的描述来搞 poc 以及 exp。但是以前没做过这类任务,所以这次打算先从复现做起。下次就直接怼源信息了。

Discuz!简介

简单来说,Discuz!是一个 BBS。很流行的那种。

漏洞前世

发现

2014 年 6 月 19,一个白帽子爆出了 Discuz 的一个任意文件删除漏洞,提交到 wooyun 平台上:
wooyun-2014-065513

分析

问题出在 source/include/spacecp/spacecp_profile.php 中:

1.png

这里的 $_GET['deletefile'] 没有经过任何处理,直接遍历他的 $key$value,然后将 $space[$key] 拼接到一个路径中,带入了系统函数 unlink() 删除此文件。

这里的 $space[$key] 是通过用户的 uid 获取的用户信息的一些字段:

2.png

我们来看一下当程序运行到上面拼接路径时,$space 的具体内容:

3.png

$space 是一个数组,里面存了所有当前用户属性信息的字段和内容。

那么,因为 $_GET['deletefile'] 是可控的,如果我们将 $_GET['deletefile']$key 设置为 $space 中存在字段,比如 $space 中存在一个用户基本信息的情感状态的字段 affectivestatus,默认是空的。

我们将 $_GET['deletefile']$key 设置成 affectivestatus,那么拼接后就成了:

4.png

其中 get('setting/attachdir').\Discuz\upload\data\attachment\profile

现在漏洞就显而易见了,因为这个 $space['affectivestatus'] 的内容就是用户信息中的情感状况,我们提前先设置一下就行了啊,设置成我们想删除的任意文件,比如 ../../../111111.txt

5.png

为啥是 ../../../ ?其实这里演示的是删 upload 下的文件,上面说过了 get('setting/attachdir') 的位置

第一步,我们先设置个人基本信息,将情感状况设置为你想删除的文件路径。

第二步,我们发送如下请求即可删除你设置的特定文件:

6.png

这里的 formhash 就是登陆后的一个 token,可以在页面源代码中看到,这个 profilesubmit 必须为 true 才能进行信息修改的操作,此时 $key=affectivestatus,看看 $space['affectivestatus'] 的内容:

7.png

这个时候通过路径拼接就达到我们删除这个 111111.txt 的目的了,提交上述第二步的请求就可以删除根目录下的 111111.txt 了。

修复

简单的在漏洞存在的地方加了一个判断:

8.png

在删除之前判断要删除的内容的 formtype 是不是 file 类型,由于用户信息的字段的 formtype 都是非 file 类型的,所以修复后导致无法在此处删除文件了。

漏洞今生

三年后,在 2017 年 9 月 29 日,Discuz 官方再次修复了这个文件,通过对比分析补丁发现同样存在一个任意文件删除漏洞,漏洞原理和触发过程跟 2014 年的漏洞一模一样,我们来看看漏洞代码。

同样在文件 source/include/spacecp/spacecp_profile.php 中,有如下代码:

9.png

10.png

这里在上传文件的时候,如果上传成功,最后在倒数第二行代码里面:

11.png?raw=true

也会进行一次删除操作,将 $space[$key] 拼接到路径后直接删除。

这里的 $space 前面已经分析过了,这个 $key 就是上传文件是遍历 $_FILES 变量中的 $key,再上传时同样没有处理 $key 的内容,所以也是可控的。

那么漏洞利用原理就是一样了,只不过是在提前设置好用户信息为路径外,第二步需要上传一个文件,让流程走到上传文件这里。

第一步,我们先设置个人基本信息,将情感状况设置为你想删除的文件路径。

第二步,我们修改一下页面属性为 type=file,然后来上传一个文件:

12.png

点击保存后,程序就会走到上传的地方,然后第一步设置的 ../../../111111.txt 文件就会被删掉。这时候的 $key 值:

13.png

这时候的 $space[$key]=$space['affectivestatus'] 的值:

大家可能注意到前面有很多 if 判断,这里需要注意上传的时候只能上传图片类型的文件,否则在:

14.png

这会判断不通过,导致 continue,走不到下面的 unlink

修复

至于漏洞修复,官方直接将此文件中的删除操作全部删除:

15.png?raw=true

EXP

用 python 简单写了一个 exp:
gayhub

后记

感觉官方的第一次修复有点敷衍,哪里漏了堵哪里。

说两点复现时候可能会踩到的坑:

  1. 使用 127.0.0.1 以及 localhost 的时候可能会出现 抱歉,您的请求来路不正确或表单验证串不符,无法提交

  2. 如果出现 非法字符已拦截 之类的,是 formhash 错了

  3. 这篇文章参考了绿盟的分析,加上了我自己的一些想法与实验。

End

What do you think?

本文标题: Discuz!(v3.4 及以下) 任意文件删除漏洞分析
原始链接: http://www.tr0y.wang/2018/04/26/Discuz-v3-4-delete/
发布时间: 2018.04.26-15:46
最后更新: 2018.11.03-20:39
版权声明: 本站文章均采用CC BY-NC-SA 4.0协议进行许可。转载请注明出处!