出品|長(zhǎng)白山攻防實(shí)驗(yàn)室(ID:A_Tree)
0x00
聲明
以下內(nèi)容,來(lái)自長(zhǎng)白山攻防實(shí)驗(yàn)室的A_Tree作者原創(chuàng),由于傳播,利用此文所提供的信息而造成的任何直接或間接的后果和損失,均由使用者本人負(fù)責(zé),長(zhǎng)白山攻防實(shí)驗(yàn)室以及文章作者不承擔(dān)任何責(zé)任。
0x02
漏洞介紹
ThinkPHP是一個(gè)開源免費(fèi)的,快速、簡(jiǎn)單的面向?qū)ο蟮妮p量級(jí)PHP開發(fā)框架,是為了敏捷WEB應(yīng)用開發(fā)和簡(jiǎn)化企業(yè)應(yīng)用開發(fā)而誕生的。
近日,監(jiān)測(cè)到其出現(xiàn)文件包含,代碼執(zhí)行漏洞,漏洞編號(hào):QVD-2022-46174,當(dāng)ThinkPHP開啟了多語(yǔ)言功能時(shí),攻擊者可以通過lang參數(shù)和目錄穿越實(shí)現(xiàn)文件包含,當(dāng)存在其他擴(kuò)展模塊如 pear 擴(kuò)展時(shí),攻擊者可進(jìn)一步利用文件包含實(shí)現(xiàn)遠(yuǎn)程代碼執(zhí)行。
0x03
漏洞類型
文件包含,代碼執(zhí)行
0x04
?漏洞影響范圍
ThinkPHP ? 6.0.1—6.0.13,5.0.x,5.1.x
0x05
漏洞復(fù)現(xiàn)
漏洞復(fù)現(xiàn)環(huán)境:
GITHUB開源項(xiàng)目:
基于ThinkPHP5.0搭建的NIUSHOP開源建站系統(tǒng)。
環(huán)境鏈接:https://github.com/znlccy/niushop
此系統(tǒng)默認(rèn)沒有開啟ThinkPHP多語(yǔ)言功能,需要做出如下修改。

修改/application/config.php文件中的lang_swit-ch_on參數(shù)為Ture

修改后再主頁(yè)測(cè)試全局lang參數(shù)是否生效:
?lang=zh-cn

?lang=en-us

上述兩個(gè)請(qǐng)求,發(fā)現(xiàn)語(yǔ)言進(jìn)行了切換,環(huán)境即搭建成功。在網(wǎng)站根目錄創(chuàng)建phpinfo文件作為測(cè)試包含文件。

訪問URL:?lang=..\..\info
執(zhí)行info文件,漏洞利用成功。

0x06
漏洞分析
先看PHP官方補(bǔ)丁內(nèi)容:在think5中修改的文件定位在了think\lang.php的detect方法,定位漏洞位置。

觀察未修復(fù)的漏洞文件:在detect()其結(jié)果為定義了一個(gè)self::$range,通過源碼分析可得,此參數(shù)受到下列參數(shù)影響:


我們將其中:$_GET[self::$langDetectVar]輸出出來(lái),驗(yàn)證參數(shù)內(nèi)容的可控程度,其參數(shù)內(nèi)容完全可控,并且detect的返回值完全由lang參數(shù)決定。

我們繼續(xù)跟進(jìn)調(diào)用Lang::detect()的文件內(nèi)容:App.php

App.php文件內(nèi)容:在config中的多語(yǔ)言機(jī)制開啟時(shí)(lang_switch_on = true)執(zhí)行了detect()將self::range通過URL中發(fā)lang參數(shù)定義,我們?cè)谏厦娣治鲞^了,接下來(lái)分別執(zhí)行了range()方法和load()方法。

我們首先跟進(jìn)range()方法:在App.php中調(diào)用range為L(zhǎng)ang::range() 因此,range()此時(shí)直接return了self::$range此參數(shù)在detect中被URL的lang參數(shù)控制。

Langset(Lang::range()):繼續(xù)跟進(jìn)如langset方法,此時(shí)$lang為URL中的lang(污點(diǎn)參數(shù))
非空后將類中私有l(wèi)angset進(jìn)行賦值,并且$this全部返回。

接下來(lái)執(zhí)行Lang::load()方法:在進(jìn)入方法前,其中傳入load()的變量中,$request->langset()為我們URL中的lang(污點(diǎn)參數(shù))。

跟進(jìn)lang():可見file參數(shù)被轉(zhuǎn)換為列表后進(jìn)行遍歷,當(dāng)遍歷的路徑存在時(shí)便include目標(biāo),file中的內(nèi)容為我們可控內(nèi)容,即導(dǎo)致文件包含。

將列表file輸出,方便觀察:可見內(nèi)容為從application\lang路徑和think\lang路徑加上我們URL中l(wèi)ang參數(shù)的內(nèi)容,但是需要我們的此時(shí)lang參數(shù)為..\..\info.php但是在file列表的內(nèi)容為info.php.php因此我們不能加上php的后綴。

那么此時(shí)我們只需要保證is_file($_file)為真即可包含實(shí)現(xiàn)文件包含漏洞。

?Lang = ..\..\info

0x07
總結(jié)
此漏洞造成原因相對(duì)簡(jiǎn)單,就是輸入?yún)?shù)過濾不嚴(yán)格,修復(fù)排查方案為查看當(dāng)前網(wǎng)站源代碼中app目錄下的config文件中l(wèi)ang_switch_on是否True即可,如果涉及到語(yǔ)言切換的需要,那么就更新thinkPHP或者手動(dòng)改一下Lang:: detect()中的源碼也行。See Bay!

