Author: p0wd3r (知道创宇404安全实验室)
Date: 2017-04-13
昨天 phpcms 发布了 9.6.1 版本,这次补丁中修复了两个安全漏洞(任意文件上传和SQL注入), 相比于任意文件上传,这个 SQL 注入虽然没那么简单粗暴,但攻击思路还是值得我们学习。
SQL 注入
版本:9.6.0
首先我们看phpcms/modules/attachment/attachments.php
中的swfupload_json
函数:
这里用safe_repalce
过滤输入,跟进这个函数:
函数将敏感字符替换为空,但问题是只执行一次,所以当输入是%*27
时*
被过滤,进而可以得到%27
。
回到swfupload_json
中,safe_replace
处理后,程序使用json_encode
+ set_cookie
生成加密的 Cookie。也就是说利用swfupload_json
我们可以构造一个含有%27
等 payload 的加密值。
不过执行swfupload_json
需要一点条件,我们看构造函数:
如果$this->userid
不为空我们才可以继续执行。$this->userid
和 sys_auth($_POST['userid_flash'], 'DECODE')
的值有关,并且程序并没有检查$this->userid
的有效性,所以只要传入的userid_flash
是个合法的加密值就可以通过检测进而使用swfupload_json
了。那么如何获取一个合法加密值呢?
这就来到了phpcms/modules/wap/index.php
中:
在 wap 模块的构造函数中程序根据siteid
生成了一个加密 Cookie,生成的值我们是可以通过响应头获取到的。
至此,我们可以通过以下两个步骤获得一个含有 payload 的加密值:
userid_flash
的值,带上 payload 访问swfupload_json
得到含有 payload 的加密值之后,我们继续找哪里可以用到这个值。 我们看phpcms/modules/content/down.php
:
这里用sys_auth
解密输入的a_k
,然后使用parse_str
(http://php.net/manual/zh/function.parse-str.php )处理a_k
,该函数的作用简单来说就是以&
分隔符,解析并注册变量。通过 IDE 的提示我们可以看到在静态的情况下$id
是未初始化的,所以我们可以通过parse_str
注册$id
进而将可控数据带入查询,另外parse_str
可以进行 URL 解码,所以之前我们得到的%27
也就被解码成了真正可以利用的'
。(parse_str
还可能导致变量覆盖的问题,详见 https://github.com/80vul/pasc2at )
所以整个攻击流程如下:
a_k
的值访问down.php
的init
函数攻击效果如图:
对a_k
进行过滤,并且对id
进行类型转换。