應(yīng)用程序與文件系統(tǒng)的交互始終是高度安全敏感的,因?yàn)檩^小的功能漏洞很容易成為可利用漏洞的來源。這種觀察在web文件管理器的情況下尤其正確,其作用是復(fù)制完整文件系統(tǒng)的功能并以透明的方式將其公開給客戶端的瀏覽器。
elFinder 是一種流行的 Web 文件管理器,常用于 CMS 和框架,例如 wordPress/ target=_blank class=infotextkey>WordPress 插件 (wp-file-manager) 或 Symfony 包,以允許對(duì)本地和遠(yuǎn)程文件進(jìn)行簡(jiǎn)單操作。在過去,elFinder一直是針對(duì)不安全配置或?qū)嶋H代碼漏洞的活躍攻擊的一部分。因此,elFinder的發(fā)布帶有一個(gè)安全的默認(rèn)配置,以防止攻擊者進(jìn)行任何惡意使用。
作為對(duì)廣泛部署的開源項(xiàng)目的定期評(píng)估的一部分,研究人員在elFinder中發(fā)現(xiàn)了多個(gè)新的代碼漏洞。在以下關(guān)于web文件管理器常見代碼漏洞的案例研究中,研究人員發(fā)現(xiàn)了五個(gè)不同的漏洞鏈,并演示了如何利用它們來獲得對(duì)底層服務(wù)器及其數(shù)據(jù)的控制。研究人員還將討論一些稍后由供應(yīng)商實(shí)現(xiàn)的補(bǔ)丁,以展示如何在用戶的代碼中防止它們。
惡意影響
我們?cè)陂_發(fā)分支上工作,提交 f9c906d。調(diào)查結(jié)果也在 2.1.57 版中得到證實(shí);都影響默認(rèn)配置(除非本文另有說明)并且不需要事先認(rèn)證。正如研究人員所提到的,利用這些漏洞會(huì)讓攻擊者在安裝elFinder的服務(wù)器上執(zhí)行任意php代碼,最終導(dǎo)致其受到攻擊。
研究人員在這篇文章中討論的發(fā)現(xiàn)均分配了 CVE-2021-32682,并成功地利用了這些發(fā)現(xiàn)來獲得代碼執(zhí)行:
刪除任意文件;
移動(dòng)任意文件;
PHP文件上傳;
參數(shù)注入;
競(jìng)爭(zhēng)條件(Race Condition);
所有這些漏洞類在向用戶公開文件系統(tǒng)的軟件中都非常常見,并且可能影響到大量產(chǎn)品,而不僅僅是elFinder。
elFinder發(fā)布了2.1.59版本,以解決研究人員負(fù)責(zé)披露的所有bug。毫無(wú)疑問,這些漏洞也會(huì)被廣泛利用,因?yàn)獒槍?duì)舊版本的漏洞已經(jīng)被公開發(fā)布,而連接器文件名是試圖破壞網(wǎng)站時(shí)要查找的路徑匯編的一部分。因此,研究人員強(qiáng)烈建議所有用戶立即將elFinder升級(jí)到最新版本。
技術(shù)細(xì)節(jié)
elFinder帶有一個(gè)用PHP編寫的后端(也稱為連接器)和一個(gè)用html和JAVAScript編寫的前端。連接器是將前端代碼的操作分派給右后端代碼以實(shí)現(xiàn)文件系統(tǒng)特性的主要腳本。連接器可以配置為禁止危險(xiǎn)操作,將上傳限制為特定的 MIME 類型:默認(rèn)安裝中有兩種不同的類型。研究人員在所謂的“最小”連接器中發(fā)現(xiàn)了漏洞。它只允許鏡像和純文本上傳,F(xiàn)TP是唯一支持的遠(yuǎn)程虛擬文件系統(tǒng):這可能是最安全的,也是最有可能部署的。
為了更好地理解研究人員將用來演示發(fā)現(xiàn)的代碼片段,研究人員將首先描述elFinder的路由是如何工作的。與許多現(xiàn)代PHP應(yīng)用程序一樣,連接器(例如connector.minimal. PHP)是唯一的入口點(diǎn)。它聲明配置指令和閉包,然后實(shí)例化elFinder(核心)和elFinderConnector (elFinder和傳輸通道之間的接口,這里是HTTP)。
屬性elFinder::$commands包含了每個(gè)有效的操作和預(yù)期的參數(shù):
php/elFinder.class.php
用戶可以通過PATH_INFO、GET或POST向cmd參數(shù)提供所需的命令參數(shù)來調(diào)用這些命令,在每個(gè)命令處理程序中,使用$args訪問參數(shù)。
為了允許遠(yuǎn)程文件系統(tǒng)(FTP、Dropbox等)與本地文件系統(tǒng)一起使用,elFinder實(shí)現(xiàn)了一個(gè)文件系統(tǒng)抽象層(elFinderVolumeDriver) ,所有驅(qū)動(dòng)程序都在該層之上構(gòu)建。然后文件通過它們的卷名(例如t1_是垃圾,l1_是默認(rèn)的本地卷)和url安全的名稱Base64來引用。
首先深入研究一個(gè)任意文件刪除漏洞鏈,它由兩個(gè)不同的漏洞組成。
刪除任意文件
PHP 核心不提供運(yùn)行后臺(tái)線程或執(zhí)行同步和進(jìn)程間通信的有效方法。 elFinder 試圖通過大量使用臨時(shí)文件和請(qǐng)求后掛鉤來平衡這一點(diǎn)。例如,用戶可以通過調(diào)用同名方法來終止正在進(jìn)行的操作:
php/elFinder.class.php
可以看到,[1]和[2]存在一個(gè)代碼漏洞:用戶控制的參數(shù)在沒有事先檢查的情況下被連接到一個(gè)完整的路徑中。對(duì)于[1],它最終會(huì)創(chuàng)建一個(gè)名稱完全可控的空文件,而在[2]中,它可以用來刪除任意文件。這兩個(gè)漏洞的SonarCloud漏洞都是可用的:[1]和[2]。
由 [1] 生成的文件名將以 elfreq 為前綴,在路徑遍歷攻擊中,如果路徑中的任何足跡不存在或不是目錄,POSIX系統(tǒng)將無(wú)法解析路徑。例如,解析/tmp/i_do_not_exist/../或/ tmp / i_am_a_file / . ./將分別在ENOENT和ENOTDIR中運(yùn)行失敗。這個(gè)先決條件使得利用這兩個(gè)漏洞不可能按原樣進(jìn)行,并且需要另一個(gè)漏洞,例如創(chuàng)建任意目錄的能力。
然后攻擊者可以查看命令mkdir并發(fā)現(xiàn)允許這種行為的原語(yǔ),下面是它的頂層處理程序,出現(xiàn)在它通過文件系統(tǒng)抽象層之前:
php/elFinder.class.php
elFinderVolumeDriver 中存在一個(gè)通用實(shí)現(xiàn)來處理應(yīng)該創(chuàng)建的卷和路徑。它將使用文件系統(tǒng)上的卷絕對(duì)路徑作為第一個(gè)參數(shù)和目標(biāo)名稱作為第二個(gè)參數(shù)調(diào)用 [1] 中特定于卷的實(shí)現(xiàn):
php/elFinderVolumeDriver.class.php
它的定義如下:
php/elFinderVolumeLocalFileSystem.class.php
elFinderVolumeLocalFileSystem::_joinPath() 只是將兩個(gè)值連接起來,導(dǎo)致路徑遍歷漏洞。這提供了在本地文件系統(tǒng)上創(chuàng)建任意空文件夾的原語(yǔ)。雖然本身不是漏洞,但它將允許利用上述漏洞。
同樣值得注意的是,rm命令中出現(xiàn)了完整路徑公開,公開給定文件在本地文件系統(tǒng)上的絕對(duì)路徑:
php/elFinderVolumeDriver.class.php
這個(gè)漏洞的影響很大程度上取決于環(huán)境:它可能與其他的elFinder漏洞結(jié)合在一起,用于在其他應(yīng)用程序中觸發(fā)有趣的行為(例如刪除WordPress的wp-config.php文件以獲得代碼執(zhí)行)或用于影響現(xiàn)有的安全措施(例如刪除.htaccess文件)。
通過改進(jìn)
elFinderVolumeLocalFileSystem::_joinPath()的實(shí)現(xiàn)來斷言最終路徑不會(huì)在基路徑之外,這個(gè)漏洞已經(jīng)被修復(fù)了。作為加固措施,還在代碼庫(kù)中添加了幾個(gè)對(duì)basename()的調(diào)用。
移動(dòng)任意文件
相同的
elFinderVolumeLocalFileSystem::_joinPath() 方法用于其他操作,例如重命名:它結(jié)合了一個(gè)卷基本目錄和一個(gè)用戶提供的目標(biāo)名稱。因此,它很容易受到研究人員剛才描述的漏洞的攻擊。
在執(zhí)行所有負(fù)責(zé)解碼路徑并確保允許目標(biāo)擴(kuò)展名的代碼之后,
elFinderVolumeLocalFileSystem::rename()的實(shí)際實(shí)現(xiàn)如下面的代碼片段所示:
php/elFinderVolumeLocalFileSystem.class.php
雖然目標(biāo)擴(kuò)展名仍然受到 MIME 檢查的嚴(yán)格限制,但對(duì)于未經(jīng)身份驗(yàn)證的攻擊者來說,根據(jù)環(huán)境,通過覆蓋authorized_keys、composer.json 等文件,該原語(yǔ)足以在服務(wù)器上執(zhí)行命令。這個(gè)漏洞已經(jīng)用研究人員之前討論過的同一個(gè)補(bǔ)丁修復(fù)了。
上傳 PHP 文件
對(duì)于大多數(shù)PHP應(yīng)用程序來說,elFinder面臨的最大威脅是攻擊者可以將PHP腳本上傳到服務(wù)器,因?yàn)闆]有任何東西(除了經(jīng)過加固的web服務(wù)器配置)可以阻止他們直接訪問它來執(zhí)行它的內(nèi)容。維護(hù)人員最初試圖通過制作一個(gè)將危險(xiǎn)的MIME類型與相關(guān)擴(kuò)展關(guān)聯(lián)起來的塊列表來防御:
php/elFinderVolumeDriver.class.php
在Ubuntu 20.10上的Apache HTTP 2.4.46-1ubuntu1的測(cè)試環(huán)境中,默認(rèn)配置聲明 .phar 文件應(yīng)該被視為 Application/x-httpd-php ([1]) 并被解釋為:
在Debian的穩(wěn)定版本中也可以看到這種配置,雖然對(duì)文件的內(nèi)容執(zhí)行另一遍MIME類型檢測(cè),因?yàn)镻HP解釋器允許在解釋文件的任何地方使用語(yǔ)句(例如PHP可以放在一些虛擬數(shù)據(jù)之后),因此也可以很容易被繞過。
修復(fù)很簡(jiǎn)單:它聲明 .phar 文件與默認(rèn)情況下不允許的 MIME text/x-php 相關(guān)聯(lián)。
參數(shù)注入
在elFinder如此強(qiáng)大的默認(rèn)功能中,用戶可以選擇多個(gè)文件,并使用zip、rar和7z等外部工具對(duì)它們進(jìn)行壓縮。該函數(shù)在名為archive的操作下被發(fā)布:
php/elFinder.class.php
請(qǐng)注意,即使上傳文件被禁止,用戶也可以通過對(duì)現(xiàn)有文件調(diào)用archive命令來創(chuàng)建壓縮,該實(shí)現(xiàn)特定于正在使用的虛擬文件系統(tǒng)。研究人員只關(guān)注默認(rèn)的命令行,因?yàn)樗怯?br />elFinderVolumeLocalFileSystem繼承的,elFinderVolumeLocalFileSystem創(chuàng)建了完整的命令行([1]),并使用默認(rèn)shell([2])執(zhí)行它:
php/elFinderVolumeLocalFileSystem.class.php
name的值來自用戶控制的參數(shù)name的值來自用戶控制的參數(shù)_GET['name'],雖然使用escapeshellarg()正確地轉(zhuǎn)義以防止使用命令替換序列,但程序?qū)L試將此值解析為標(biāo)志 (--foo=bar),然后解析為位置參數(shù)。還值得注意的是,在選擇 ZIP壓縮程序的情況下,用戶的值以. ZIP作為后綴。
命令壓縮包實(shí)現(xiàn)了一個(gè)完整性測(cè)試特性(-T),可以與-TT一起使用該特性來指定要運(yùn)行的測(cè)試命令。在本例中,它為攻擊者提供了一種使用此參數(shù)注入執(zhí)行任意命令的方法。
為了能夠利用此漏洞,攻擊者需要?jiǎng)?chuàng)建一個(gè)虛擬文件(例如a.txt),將其壓縮以創(chuàng)建a.zip,然后以原始文件和壓縮為目標(biāo)調(diào)用壓縮操作,使用的名稱如下: TmTT="$(id>out.txt)foooo"。
生成的命令行將是 zip -r9 -q '-TmTT="$(id>out.txt)foooo".zip' './a.zip' './a.txt',從而執(zhí)行 id 并記錄其標(biāo)準(zhǔn)輸出到 out.txt,此文件將與 elFinder 界面中的其他文檔一起使用。
當(dāng)需要修復(fù)這個(gè)漏洞時(shí),壓縮操作不能很好的運(yùn)行。通常基于POSIX的方法,故不能在此處應(yīng)用,因?yàn)閦ip將退出,并出現(xiàn)以下漏洞:
然后維護(hù)人員決定在壓縮名稱前加上 ./ 以防止任何參數(shù)注入的風(fēng)險(xiǎn),他們還決定在同一個(gè)補(bǔ)丁中加強(qiáng)對(duì)其他壓縮程序(7z、rar等)的調(diào)用。
隔離和競(jìng)爭(zhēng)條件
看看研究人員在這個(gè)案例研究中的最后發(fā)現(xiàn),由于壓縮文件無(wú)法上傳,因此無(wú)法在默認(rèn)配置中利用隔離特性中的此漏洞,由于設(shè)計(jì)特點(diǎn),該函數(shù)可能會(huì)導(dǎo)致未來的安全問題。
隔離的基本原理是壓縮文件可能包含不需要的文件(主要是PHP腳本) ,如果沒有首先運(yùn)行安全檢查(例如,使用 MIME 驗(yàn)證),則不應(yīng)在當(dāng)前文件夾中提取這些文件。因此,elFinder選擇將壓縮文件提取到一個(gè)名為.quarantine的文件夾中,該文件夾位于files/文件夾下,
elFinderVolumeLocalFileSystem::_extract()為每個(gè)壓縮文件提取生成一個(gè)隨機(jī)的目錄名(位于[1]):
php/elFinderVolumeLocalFileSystem.class.php
這可以通過strace或inotify套件動(dòng)態(tài)確認(rèn),例如這里有一個(gè)包含PHP文件的壓縮文件:
這個(gè)進(jìn)程如下:
創(chuàng)建了一個(gè)名為
efbf975ccbac8727f434574610a0f1b6 的文件夾;
在
efbf975ccbac8727f434574610a0f1b6 中創(chuàng)建了一個(gè)名為 win.php 的文件;
數(shù)據(jù)被寫入win.php;
win.php被刪除;
efbf975ccbac8727f434574610a0f1b6被刪除;
如果服務(wù)器被配置為列出目錄,這個(gè)行為很容易被利用,因?yàn)榭梢栽?MIME 驗(yàn)證步驟和刪除它們之前訪問危險(xiǎn)文件(例如 .php)。然而,如果無(wú)法以這種方式找到隨機(jī)目錄名稱,那么競(jìng)爭(zhēng)條件窗口太小而無(wú)法考慮使用暴力破解的攻擊。
攻擊者可能會(huì)發(fā)現(xiàn)復(fù)制操作可用于內(nèi)部文件夾,例如 .quarantine,并復(fù)制任何文件,而不管其內(nèi)容如何。雖然它本身是一個(gè)無(wú)害的函數(shù)漏洞,但它可以與隔離函數(shù)鏈接在一起,以便在刪除之前復(fù)制包含研究人員提取的壓縮文件夾。復(fù)制的文件夾在界面中可見,并允許攻擊者繞過隨機(jī)名稱訪問惡意腳本,最終允許執(zhí)行任意代碼。
作為修復(fù)措施,維護(hù)人員決定將.quarantine文件夾移到files/之外。
elFinderVolumeLocalFileSystem抽象層不知道此文件夾之外的任何內(nèi)容,從而防止對(duì).quarantine執(zhí)行任何意外操作。
總結(jié)
在這個(gè)案例研究中,研究人員研究了在web文件管理器中常見的關(guān)鍵代碼漏洞。本文的研究證明無(wú)害的漏洞通常可以組合起來形成有害漏洞鏈,比如獲得任意代碼執(zhí)行。研究人員認(rèn)為,記錄和報(bào)告這些漏洞是很重要的,以緩解漏洞鏈,并減少類似漏洞的風(fēng)險(xiǎn)。






