最近几天圈里放出来一波phpcms的0day漏洞,这就是其中一个。此漏洞觉得很有意思,而且利用也需要好几个步骤,Payload完全可以绕过WAF检测。
漏洞分析
这里我们使用反推的方法来分析这个漏洞过程。
漏洞触发点在文件/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#。
继续往下看array(‘id’=>$id)进入了数据库操作,这里的id就是从parse_str函数处理$a_k后得到的内容,因为系统中默认是没有定义这个id的,正好通过parse_str处理后注册了id变量。
现在的问题就是:
我们怎么得到这个$a_k的值,因为解密,肯定存在加密,而且这里的加密是需要系统中的auth_key的,所以我们本地使用加解密函数进行数据加解密就行不通了。
那么就只能在当前系统中找到一处能加密的接口,并且可以输出解密后内容的地方。
在文件/phpcms/modules/attachment/attachments.php,swfupload_json函数:
这里从GET获取了src参数内容,并且通过safe_replace函数处理
然后通过json格式化后进入了set_cookie函数。
我们先来看看safe_replace函数的内容,文件\phpcms\libs\functions\global.func.php:
功能就是把一些符号给替换掉了,比如%27,*,’,”等。
但是这里有一个问题如果我们传入%2*7通过safe_replace函数后变成了%27
然后门继续来看看这个set_cookie函数,文件\phpcms\libs\classes\param.class.php
可以看到,我们传入set_cookie(‘att_json’,$json_str);,将我们传入的att_json+系统中cookie的前缀作为set-cookie的key=前缀_att_json,将$json_str的内容通过sys_auth函数加密后最为set-cookie的value值。这里在sys_auth进行加密时默认使用的是system里面的auth_key,跟我们前面进行解密时使用的是同一个auth_key。
到这里,我们就清楚了:
第一步传入src参数;
第二步将传入的内容通过加密后返回到Cookie值;
第三步将返回的Cookie值传递给a_k参数
第四步a_k参数解密后进入数据库操作
因为整个过程中传递数据时是加密的,所有无视waf的防御,虽然有safe_replace函数处理,但是我们上面已经简单绕过了。
需要注意的时,在我看到的几篇分析文章中,都没有提到为什么第一步先要获取一个cookie并带入第二步获取加密的payload数据,这里我们看一下:
还是在attachments.php文件
这里一目了然,为什么需要带上cookie 访问,因为不带cookie的话就直接跳到登录了。
这里有两种方式:
直接从cookie中获取名为:前缀_userid的cookie内容;
POST一个userid_flash
但是这两个方法获取的内容,多需要通过sys_auth解密,如果解密失败也会跳转到登录。
所以我们传入的cookie内容必须是合法的cookie,也就是通过set_cookie函数设置的cookie,因为set_cookie函数设置cookie时会通过sys_auth加密,这样解密就合法了。
那么从哪里无添加直接获取这个cookie 了,系统中应该有很多,这里使用的是wap模块里面的接口,/phpcms/modules/wap/index.php:
这里GET获取siteid,然后为siteid设置cookie,返回的就是前缀_siteid为key的cookie。
然后这个cookie就可以拿来给下一步用了。
漏洞利用:
获取到这里的cookie:
KhLUs_siteid=923aWILP69vS49T0lonOkl-ZEWFgBRxEdmRHCEUx
然后将设置第二步的cookie:
KhLUs_userid=923aWILP69vS49T0lonOkl-ZEWFgBRxEdmRHCEUx
带上这个cookie访问:
上面标红的那一段为我们构造的payload。
此时得到cookie:
KhLUs_att_json=a217vsJZ1FMqAjbenpUAOGzykDTKwL3z0aM6RWBZnBlh6RL6BDS8vlPFt9wPIo5mwketJHkRsNnDJr1ovMGoYTKNqLxN9NyPXt072g-7ZSR_3Rg_gdeXJW_j5VWaIIShkZFxtR87Fz9ggw6kA4ys8df0MEmMBqJFLqNBw34GZq5WBc4vW2L9dMy4WbdyKV6ofWNH2uCsQDOf-DRBYUvFg099BEUk
第三步我们将cookie,KhLUs_att_json的值付给a_k参数:
然后加密的payload通过解密最后进入数据库操作,导致sql注入产生。
注入数据的利用请见附件中的exp。
注入发生后,进一步利用就各种发挥咯。
漏洞修复:
官方发布了9.6.1版本,4月12日也出了补丁,补丁地址:
来看一下补丁的修复情况:
可以看到这里对$a_k进行过滤,并且对id进行intval转换。
所以请升级到最新版。
如果您需要了解更多内容,可以
加入QQ群:570982169
直接询问:010-68438880