ThinkPHP 5.1.x~5.2.x全版本 RCE 漏洞分析
- 2019 年 10 月 8 日
- 筆記
大概看了下,這個洞跟5.0的原理大致相同,都是利用Reuqest類的Method方法覆蓋了 $this->filter
屬性,然後進入 filterValue
調用 call_user_func($filter,$value)
, $value
為當前請求參數和URL地址中的參數合併,從而導致RCE。
漏洞驗證
測試版本:Thinkphp_5.1.1 修補程式:https://github.com/top-think/framework/commit/2454cebcdb6c12b352ac0acd4a4e6b25b31982e6 需要在入口文件處關閉報錯。

payload
c=exec&f=calc.exe&&_method=filter&

流程分析
在獲取應用調度資訊時會調用Request類的method方法獲取當前的請求類型

且 $this->config->get('var_method')
外部可控,即 $this->method
我們可控,從而我們可以通過 $this->{$this->method}($_POST)
調用任意方法。


跟進 filter
方法,發現我們post的數據可以覆蓋 $this->filter
屬性。

回到App類,由於我們開啟了 $this->debug
從而可以進入 Request
類的 param
方法。

跟進 param
方法, $this->param
為當前請求參數和URL地址中的參數合併。然後進入 input
方法。

跟進 input
方法,因為 $data
為上面提到的 $this->param
即數組,從而進入if條件執行 array_walk_recursive($data,[$this,'filterValue'],$filter);

查閱 array_walk_recursive
函數可知,該函數會調用 $this->filterValue
函數,把 $data
數組的每個值作為其第一個參數,鍵名作為第二個參數,並且把 $this->filter
作為第三個參數。

繼續跟進 filterValue
方法,發現調用了 call_user_func($filter,$value)
, $filter
為剛開始我們覆蓋的 $this->filter
屬性的遍歷鍵值,等於 $_POST
數組。 $value
為當前請求參數和URL地址中的參數合併數組 $this->param
的鍵值。

當遍歷到 $this->param
的第二個鍵值 calc.exe
和 $filters
的第一個鍵值 exec
時,成功執行命令,彈出了計算器。

修補程式分析

與5.0一樣,對錶單請求類型偽裝變數添加了白名單。