XXE漏洞——XML實體定義引起的兼容性問題
一、XML基礎知識
XML指可擴展的標記語言(Extensible Markup Language),類似於HTML(超文本標記語言);
XML被設計用來結構化、存儲以及傳輸信息,其焦點是數據的內容;
XML沒有任何預定義的標籤,所有標籤均由開發者自定義,開發者可以依據需要定製與業務匹配的結構化標籤;
XML是對HTML的補充,在大多數WEB應用中,XML用於傳輸數據,HTML用於格式化並顯示數據(XML是獨立於軟件和硬件的信息傳輸工具);
XML文檔結構樹包括XML聲明、DTD文檔類型定義(可選)、文檔元素,這種樹結構必須包含根節點,該節點是所有其他元素的父元素。
<?xml version="1.0" encoding="UTF-8"?><!--XML聲明--> <!--文檔類型定義--> <!DOCTYPE book [ <!ELEMENT book (bId, bName)> <!ELEMENT bId (#PCDATA)> <!ELEMENT bName (#PCDATA)> ]> <!--文檔元素--> <books> <book> <bId>1</bId> <bName>Java編程思想</bName> </book> <book> <bId>2</bId> <bName>Python實戰</bName> </book> </books>
DTD(文檔類型定義)的作用是定義XML文檔的合法構建模塊,DTD可以在XML文檔內聲明,也可以引用外部的dtd文件。
內部聲明DTD
<!DOCTYPE 根元素 [元素聲明]>
引用外部DTD
<!DOCTYPE 根元素 SYSTEM "文件名">
or
<!DOCTYPE 根元素 PUBLIC "PUBLIC_ID" "文件名">
內部聲明實體
<!ENTITY 實體名稱 "實體的值">
引用外部實體
<!ENTITY 實體名稱 SYSTEM "URI“>
or
<!ENTITY 實體名稱 PUBLIC "PUBLIC_ID" "URI">
二、XML外部實體注入(XML External Entity)
當允許引用外部實體時,通過構造惡意內容,可導致讀取文件、執行系統命令、佔用內存、探測內網端口、攻擊內網網站等危害。
引用外部實體的方式有多種,比如下面這種引用方式可以讀取任意文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE book [ <!ENTITY book SYSTEM "F:///etc/passwd"> ]> <books> <book> <bId>1</bId> <bName>&book;</bName> </book> </books>
實體注入除了可以讀取文件之外,還可以將文件內容發送到攻擊者網站、執行系統命令、探測內網端口、攻擊內網網站等。
三、防禦XXE攻擊
方案一:使用開發語言提供的禁用外部實體的方法
Java:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(true);
Python:
from lxml import etree xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
方案二:過濾用戶提交的XML數據
關鍵詞:<!DOCTYPE、<!ENTITI、SYSTEM、PUBLIC等
四、在瀏覽器中的體現
使用XML傳輸數據時,當數據中含有實體時,需要在文檔定義中聲明實體XML解析器才能正確的解析數據。
當數據中可能出現實體時,需要在文檔聲明中定義好實體內容;
這種處理比較簡便,在大多數瀏覽器中也都可以正確解析數據,然而如果需要支持低版本的瀏覽器,那麼這樣處理去含有實體定義的XML數據就顯得有點危險了。
例如,在IE9、IE8上,當瀏覽器試着去解析一個含有實體定義的XML數據時,由於該瀏覽器內部會將定義的實體當作實體注入攻擊,因此數據解析遇到實體定義時,瀏覽器直接拋出異常。
解決方案:
方案一:
更換高版本瀏覽器,高版本瀏覽器不會對內部實體定義做處理。
方案二:
改用其他方式傳輸數據,如JSON。