目錄:
- 前言
- 漏洞原理
- Demo演示
- 如何發現XXE漏洞
- XXE其他危害
- 案例-微信支付的XXE
- 修復建議
前言:
什么是XXE漏洞?
XXE全稱是——XML External Entity
簡單來說,XXE就是XML外部實體注入。當應用程序允許引用外部實體時,通過構造惡意內容,就可以導致任意文件讀取、系統命令執行、內網端口探測、攻擊內網網站等危害。
什么是XML,如需詳細了解,可參考XML菜鳥教程。
一、漏洞原理
1、DTD
文檔類型定義(DTD)可定義合法的XML文檔構建模塊。它使用一系列合法的元素來定義文檔的結構。DTD 可被成行地聲明於 XML 文檔中,也可作為一個外部引用。
什么是DTD,如需詳細了解,可參考DTD菜鳥教程。
1.1、內部的 DOCTYPE 聲明:
<!DOCTYPE 根元素 [元素聲明]>
1.2、外部的 DOCTYPE 聲明:
<!DOCTYPE 根元素 SYSTEM "文件名">
這是包含 DTD 的 "note.dtd" 文件
1.3、DTD實體
實體是用於定義引用普通文本或特殊字符的快捷方式的變量。
-
實體引用是對實體的引用。
-
實體可在內部或外部進行聲明。
DTD內部實體聲明:
<!ENTITY 實體名稱 "實體的值">
DTD外部實體聲明:
<!ENTITY 實體名稱 SYSTEM "URI/URL">
2、XML外部實體
XML,可拓展的標記語言,(eXtensible Markup Language),用於傳輸和存儲數據。
XML文檔實例:
XML“外部實體”實例:
可以在DOCTYPE頭部標簽中通過SYSTEM關鍵字定義“實體”,這些“實體”可以訪問本地或遠程的內容。SYSTEM告訴XML解釋器,從URI中讀取實體的內容。攻擊者可以通過實體將自定義的值發送給應用程序,然后讓應用程序去呈現,比如上面就是把實體定義為passwd文件,讓XML解釋器去讀取文件。
二、Demo 演示
2.1、新建一個外部實體的XML文檔,讀取本地的某個文件。
<?xml version="1.0"?> <!DOCTYPE note [ <!ENTITY myentity SYSTEM "file:///C:/XXE.txt"> ]> <note> <to>Tove</to> <from>&myentity;</from> <heading>Reminder</heading> <body>Don't forget me this weekend</body> </note>
2.2、創建DOM解釋器解析上面的XML文件
package Eleven; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.*; public class Test { public static void main(String[] args) throws Exception{ /** *創建DOM解釋器解析XML文件 */ // 把要解析的 XML 文檔轉化為輸入流,以便 DOM 解析器解析它 InputStream is = new FileInputStream("D:\\2-code\\Eleven\\src\\main\\resources\\templates\\note2.xml"); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //創建DOM模式的解析器工廠 DocumentBuilder builder = factory.newDocumentBuilder(); //調用工廠的方法得到DOM解析器對象 Document doc = builder.parse(is);//調用 DOM 解析器對象的 parse() 方法解析 XML 文檔,得到代表整個文檔的 Document 對象 NodeList nodeList = doc.getElementsByTagName("from");//根據元素名稱獲取元素值 System.out.println(nodeList.item(0).getTextContent()); } }
2.3、執行后的結果
三、如何發現XXE漏洞
3.1、尋找XML輸入點
比如Content-Type:text/xml, post的數據包含XML格式,如:
<forgot><username>admin</username></forgot>
請求頭中添加Content-Type:text/xml,或Content-type:application/xml
同時,POST中添加payload
3.2 通過關鍵字,在代碼中查找XML解釋器,確認解釋器是否針對此漏洞做了安全限制(禁用外部實體、過濾關鍵字等)
關鍵字:DocumentBuilderFactory等
四、XXE其他危害
4.1、任意文件讀取(如上)
通過提交自動以URI,可以讀取任意文件(本地或遠程)。
還可以通過DTD文檔引入外部DTD文檔,再引入外部實體聲明,如下:
以上輸入有回顯的情況,/etc/passwd可以直接被顯示出來,無回顯的情況,需要把文件外發至遠程服務器,具體如下:
4.2、拒絕服務攻擊
原理為:構造惡意的XML實體文件耗盡可用內存,因為許多XML解析器在解析XML文檔時傾向於將它的整個結構保留在內存中,解析非常慢,造成了拒絕服務器攻擊。
4.3、測試后端服務器的開放端口
通過返回的“Connection refused”可以知道該81端口是closed的,而80端口是open的。
4.4、后端WEB漏洞如果可以通過URL加以利用,可造成WEB漏洞攻擊
4.5、命令執行
PHP要開啟PECL上的Expect擴展。
五、案例-微信支付的XXE
漏洞描述:
微信支付提供了一個 api 接口,供商家接收異步支付結果,微信支付所用的java sdk在處理結果時可能觸發一個XXE漏洞,攻擊者可以向這個接口發送構造惡意payloads,獲取商家服務器上的任何信息,一旦攻擊者獲得了敏感的數據 (md5-key and merchant-Id etc.),他可能通過發送偽造的信息不用花錢就購買商家任意物品
如圖所示:
上述類中實現了xmltoMap和maptoXml這兩個方法,而這次的微信支付的xxe漏洞爆發點就在xmltoMap方法中,當構建了 documentBuilder 以后就直接對傳進來的 strXML 解析了,而不巧的是 strXML 是一處攻擊者可控的參數,於是就出現了 XXE 漏洞。
六、修復建議
1、配置XML處理器使用禁用DTD、禁止外部實體解析
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); factory.setFeature("http://xml.org/sax/features/external-general-entities", false); factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
2、通過黑名單過濾用戶提交的XML數據
關鍵詞:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC