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函數:

這里用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 的加密值:
- 訪問 wap 模塊得到一個普通的加密 Cookie

- 將上面得到的加密 Cookie 作為
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 )
所以整個攻擊流程如下:
- 通過 wap 模塊構造含有 payload 的加密值
- 將加密值作為
a_k的值訪問down.php的init函數
攻擊效果如圖:

0x02 補丁分析

對a_k進行過濾,并且對id進行類型轉換。
0x03 參考
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/275/