昨天在朋友圈看到某乙方的安全實驗室發布了一個ThinkPHP3.2.x RCE漏洞通報,以為TP3.2的版本研究出新的漏洞姿勢,剛好記得騰訊的XSRC應該是基於TP3.2的版本進行開發的,於是跟進了這個漏洞。
根據描述說:
標題:ThinkPHP3.2.x_assign方法第一個變量可控=>變量覆蓋=>任意文件包含=>RCE 作者:北門-王境澤@玄甲實驗室 審稿:夢想小鎮-晨星@玄甲實驗室 攻擊方式:遠程 漏洞危害:嚴重 攻擊url: http://x.x.x.x/index.php?m=Home&c=Index&a=index&value[_filename]=.\Application\Runtime\Logs\Home\21_06_30.log 標簽:ThinkPHP3.2.3 RCE 變量覆蓋 文件包含 代碼執行
於是開始對XSRC的源碼進行審計:
發現並沒有這樣寫的
於是手工構造了一下:
把$key的變量移除search_key的,變為第一個參數為可控變量。
根據payload發現,這個RCE需要依賴本地文件包含,TP的有個runtime log可以記錄錯誤model到log中,構造比較簡單index.php?c=<?php=phpinfo();?>
然后根據payload 繼續測試,&value[_filename]=.\Application\Runtime\Logs\Home\21_06_30.log,(LOG修改自己的日期),發現依舊不成功,決定再繼續讀一遍他的分析,附圖直接引用文章上的,已經列出的分析很清晰了
可控變量進入assign方法賦值給$this→tVar變量:
賦值結束后進入display方法中,display方法開始解析並獲取模板文件內容,此時模板文件路徑和內容為空:
程序進入fetch方法中,傳入的參數為空,程序會去根據配置獲取默認的模板文件位置(./Application/Home/View/Index/index.html)。之后,系統配置的默認模板引擎為think,所以程序進入else分支,獲取$this→tVar變量值賦值給$params,之后進入Hook::listen方法中。l
listen方法處理后,進入exec方法中
進入exec方法中,處理后調用Behavior\ParseTemplateBehavior類中的run方法處理$params這個帶有日志文件路徑的值。
程序進入run方法中,一系列判斷后,進入else分支,調用Think\Template類中的fetch方法對變量$_data(為帶有日志文件路徑的變量值)進行處理。
進入Think\Template類中的fetch方法,獲取緩存文件路徑后,進入Storage的load方法中。
跟進到Storage的load方法中,$_filename為之前獲取的緩存文件路徑,$var則為之前帶有_filename=日志文件路徑的數組,$vars不為空則使用extract方法的EXTR_OVERWRITE默認描述對變量值進行覆蓋,之后include該日志文件路徑,造成文件包含。
這個是摘抄分析的原文,這里有個重點是$assign的第一個參數,將會導入TP中,獲取$this→tVar變量值賦值給$params
最終被include,文件包含。
然后修改paylload:
成功執行,這個漏洞主要依賴代碼的xxx[_filename] 在和同事交流的時候,發現這個洞,其實14年就提處來了,並且烏雲已經報告過了,不知道為什么今天又發出來了。。
phith0n之前分析過一個類似的:CodeIgniter框架內核設計缺陷可能導致任意代碼執行
https://bugs.leavesongs.com/php/codeigniter%E6%A1%86%E6%9E%B6%E5%86%85%E6%A0%B8%E8%AE%BE%E8%AE%A1%E7%BC%BA%E9%99%B7%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4%E4%BB%BB%E6%84%8F%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C/
wooyun之前提交的這個:ThinkPHP遠程代碼執行隱患(需滿足特定條件)
https://wooyun.laolisafe.com/bug_detail.php?wybug_id=wooyun-2014-051906
分析的邏輯也都一樣,思路不錯,可惜是很久之前的,當做是個炒冷飯吧,可以留作一個后門小技巧。
【漏洞通報】ThinkPHP3.2.x RCE漏洞通報
https://mp.weixin.qq.com/s/_4IZe-aZ_3O2PmdQrVbpdQ
注明:本文章無惡意攻擊任何廠商並尊重廠商技術實力,應該是漏洞的作者可能也沒發現這個是歷史漏洞。