Author: p0wd3r (知道创宇404安全实验室)
Date: 2017-04-13

0x00 漏洞概述

漏洞简介

昨天 phpcms 发布了 9.6.1 版本,这次补丁中修复了两个安全漏洞(任意文件上传和SQL注入), 相比于任意文件上传,这个 SQL 注入虽然没那么简单粗暴,但攻击思路还是值得我们学习。

漏洞影响

SQL 注入
版本:9.6.0

0x01 漏洞复现

首先我们看phpcms/modules/attachment/attachments.php中的swfupload_json函数:

swfupload.png

这里用safe_repalce过滤输入,跟进这个函数:

safe_replace.png

函数将敏感字符替换为空,但问题是只执行一次,所以当输入是%*27*被过滤,进而可以得到%27

回到swfupload_json中,safe_replace处理后,程序使用json_encode+ set_cookie生成加密的 Cookie。也就是说利用swfupload_json我们可以构造一个含有%27等 payload 的加密值。

不过执行swfupload_json需要一点条件,我们看构造函数:

construct.png

如果$this->userid不为空我们才可以继续执行。$this->useridsys_auth($_POST['userid_flash'], 'DECODE')的值有关,并且程序并没有检查$this->userid的有效性,所以只要传入的userid_flash是个合法的加密值就可以通过检测进而使用swfupload_json了。那么如何获取一个合法加密值呢?

这就来到了phpcms/modules/wap/index.php中:

wap.png

在 wap 模块的构造函数中程序根据siteid生成了一个加密 Cookie,生成的值我们是可以通过响应头获取到的。

至此,我们可以通过以下两个步骤获得一个含有 payload 的加密值:

  1. 访问 wap 模块得到一个普通的加密 Cookie

userid.png

  1. 将上面得到的加密 Cookie 作为userid_flash的值,带上 payload 访问swfupload_json

encode_payload.png

得到含有 payload 的加密值之后,我们继续找哪里可以用到这个值。 我们看phpcms/modules/content/down.php

down.png

这里用sys_auth解密输入的a_k,然后使用parse_strhttp://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

所以整个攻击流程如下:

  1. 通过 wap 模块构造含有 payload 的加密值
  2. 将加密值作为a_k的值访问down.phpinit函数

攻击效果如图:

poc.png

0x02 补丁分析

patch.png

a_k进行过滤,并且对id进行类型转换。

0x03 参考


欢迎扫描以下二维码赞赏作者(微信)