上篇內容我們介紹了XXE的基礎概念和審計函數的相關內容,今天我們將繼續分享Blind XXE與OOB-XXE的知識點以及XXE防御方法,希望對大家的學習有所幫助!
上期回顧
Blind XXE與OOB-XXE
一般XXE利用分為兩大場景:有回顯和無回顯。有回顯的情況可以直接在頁面中看到Payload的執行結果或現象(帶內XML外部實體(XXE),即攻擊者可以發送帶有XXE有效負載的請求並從包含某些數據的Web應用程序獲取響應),無回顯的情況又稱為Blind XXE,可以使用外帶數據通道提取數據即帶外XML外部實體(OOB-XXE)。
以下是攻擊者如何利用參數實體使用帶外(OOB)技術竊取數據的示例。
request:

XML解析器將首先處理%file加載文件的參數實體/etc/lsb-release。接下來,XML解析器將在http://attacker.com/evil.dtd向攻擊者的DTD發出請求。
一旦處理了攻擊者的DTD,all%參數實體將創建一個名為&send的通用實體; ,其中包含一個包含文件內容的URL(例如http://attacker.com/?collect=DISTRIB_ID=Ubuntu…)。最后,一旦URL構造的&send; 實體由解析器處理,解析器向攻擊者的服務器發出請求。然后,攻擊者可以在其結尾處記錄請求,並從記錄的請求中重建文件的內容。
知道何為Blind XXE后,這里再分析一下原理:
Blind XXE原理
帶外數據通道的建立是使用嵌套形式,利用外部實體中的URL發出訪問,從而跟攻擊者的服務器發生聯系。
直接在內部實體定義中引用另一個實體的方法如下,但是這種方法行不通。

但是這樣做行不通,原因是不能在實體定義中引用參數實體,即有些解釋器不允許在內層實體中使用外部連接,無論內層是一般實體還是參數實體。

解決方案是:將嵌套的實體聲明放入到一個外部文件中,這里一般是放在攻擊者的服務器上,這樣做可以規避錯誤。
如下:payload

nc -lvv port 監聽即可獲得請求回顯內容。
XXE利用
示例無回顯讀取本地敏感文件(Blind OOB XXE):
此部分演示借用php中XXE進行說明
xml.php

test.dtd

payload:


整個調用過程:我們從 payload 中能看到 連續調用了三個參數實體 %remote;%int;%send;,這就是我們的利用順序,%remote 先調用,調用后請求遠程服務器上的 test.dtd ,有點類似於將 test.dtd 包含進來,然后 %int 調用 test.dtd 中的 %file, %file 就會去獲取服務器上面的敏感文件。
將 %file 的結果填入到 %send 以后(因為實體的值中不能有 %, 所以將其轉成html實體編碼 %),我們再調用 %send; 把我們的讀取到的數據發送到我們的遠程 vps 上,這樣就實現了外帶數據的效果,完美的解決了 XXE 無回顯的問題。
新的利用:如圖所示

注意:
1、其中從2012年9月開始,Oracle JDK版本中刪除了對gopher方案的支持,后來又支持的版本是 Oracle JDK 1.7 update 7 和 Oracle JDK 1.6 update 35 。
2、libxml 是 PHP 的 xml 支持。
netdoc協議

另外對於帶外XXE還可以通過burp 進行測試如(附上兩張圖):


關於burp此插件還可在多個場景測試中用到,比如XSS、SQL、SSRF等。
最后,分享一下審計中遇到兩個XXE的審計與利用思路過程。
第一處出現在系統使用的org.dom4j.DocumentHelper調用的類函數下。
在源碼中搜索關鍵字DocumentHelper.parseText
得到:
\xxx\***\***.java
Line 303: document = DocumentHelper.parseText(xml);
\xxx\***\XmlParser.java
Line 51: Document doc = DocumentHelper.parseText(xmlStr);
\\xxx\***\***Task.java
Line 350: Document document = DocumentHelper.parseText(result);
\\xxx\***\***Action.java
Line 237: Document document = DocumentHelper.parseText(mapDataForOut);
\\xxx\***\xxxAction.java
Line 259: Document document = DocumentHelper.parseText(mapDataForOut);
\\xxx\***\xxx.java
Line 120: Document doc = DocumentHelper.parseText(policyXml.replaceAll("_lnx", ""));
Line 125: doc = DocumentHelper.parseText(node.asXML);
\\xxx\***tion.java
Line 109: Document doc = DocumentHelper.parseText(xmlStr);
\\xxx\***.java
Line 58: doc = DocumentHelper.parseText(xml); // 將字符串轉為XML
\xxx\***.java
Line 92: doc = DocumentHelper.parseText(xml);
Line 97: oldDoc = DocumentHelper.parseText(vaildXml);
\\xxx\***ObjConverter.java
Line 173: Document document = DocumentHelper.parseText(xml);
\\xxx\***.java
Line 949: doc = DocumentHelper.parseText(infor.getContent);
\\xxx\***Utility.java
Line 1203: Document doc = DocumentHelper.parseText(result);
\\xxx\***xxxService.java
Line 177: Document doc = DocumentHelper.parseText(requestHeader);
\xxx\***\EventParser.java
Line 83: Document doc = DocumentHelper.parseText(xmlStr);
Line 185: Document doc = DocumentHelper.parseText(xmlStr);
Line 229: Document doc = DocumentHelper.parseText(xmlStr);
Line 306: DocumentHelper.parseText(contentXml)).replaceAll("<", "<").replaceAll(">", ">").replaceAll("==amp;",
\\xxx\***\XMLMessageUtil.java
Line 24: doc = DocumentHelper.parseText(xml);
Line 131: tempDoc = DocumentHelper.parseText(xml);
Line 224: document = DocumentHelper.parseText("");
\xxx\***\XmlParser.java
Line 51: Document doc = DocumentHelper.parseText(xmlStr);
\\xxx\***.java
Line 244: Document doc = DocumentHelper.parseText(xmlStr);
其中,\xxx\***\XMLMessageUtil.java

代碼中使用org.dom4j.DocumentHelper.parseTest解析XML文件。
第二處,發現位置是在查看web.xml文件中AxisServlet的servlet-mapping配置,發現URL地址包含以下路徑或后綴就可被攻擊利用。

在通過訪問以下URL即可訪問到AxisServlet服務,可對其進行XXE漏洞攻擊。
https://ip/***/servlet/AxisServlet
POC:
在復現時由於目標主機無法訪問外網,所以需要在本地主機上搭建測試環境,具體的復現過程如下:
1)新建目錄xxe_test,復制下面文件放入
test.dtd

2)在xxe_test目錄下運行如下命令,監聽8080端口(檢查防火牆是否開放該端口)
Python -m SimpleHTTPServer 8080
3)運行以下腳本,啟動ftp服務器(檢查防火牆是否開放21端口)
Python xxe-ftp.py


4)發送以下報文:


漏洞截圖
成功獲取到受害主機的/etc/shadow文件

結束。
另外,也可以使用工具XXEinjector 完成帶外攻擊。
XXE防御
使用語言中推薦的禁用外部實體的方法:

以上是今天的全部內容,希望小伙伴們認真學習,后面我們還會分享其他的漏洞內容,大家敬請期待!