要了解xxe漏洞,那么一定得先明白基礎知識,了解xml文檔的基礎組成。另外php版本大于5.4.45的默認不解析外部實(shí)體
XML用于標記電子文件使其具有結構性的標記語(yǔ)言,可以用來(lái)標記數據、定義數據類(lèi)型,是一種允許用戶(hù)對自己的標記語(yǔ)言進(jìn)行定義的源語(yǔ)言。XML文檔結構包括XML聲明、DTD文檔類(lèi)型定義(可選)、文檔元素

通過(guò) DTD,您的每一個(gè) XML 文件均可攜帶一個(gè)有關(guān)其自身格式的描述。
通過(guò) DTD,獨立的團體可一致地使用某個(gè)標準的 DTD 來(lái)交換數據。
而您的應用程序也可使用某個(gè)標準的 DTD 來(lái)驗證從外部接收到的數據。
您還可以使用 DTD 來(lái)驗證您自身的數據。
所有的 XML 文檔(以及 HTML 文檔)均由以下簡(jiǎn)單的構建模塊構成:
下面是每個(gè)構建模塊的簡(jiǎn)要描述。
1,元素
元素是 XML 以及 HTML 文檔的主要構建模塊,元素可包含文本、其他元素或者是空的。
實(shí)例:
- <body>body text in between</body>
- <message>some message in between</message>
空的 HTML 元素的例子是 'hr'、'br' 以及 'img'。
2,屬性
屬性可提供有關(guān)元素的額外信息
實(shí)例:
<img src='computer.gif' />
3,實(shí)體
實(shí)體是用來(lái)定義普通文本的變量。實(shí)體引用是對實(shí)體的引用。
4,PCDATA
PCDATA 的意思是被解析的字符數據(parsed character data)。
PCDATA 是會(huì )被解析器解析的文本。這些文本將被解析器檢查實(shí)體以及標記。
5,CDATA
CDATA 的意思是字符數據(character data)。
CDATA 是不會(huì )被解析器解析的文本。
DTD(文檔類(lèi)型定義)的作用是定義 XML 文檔的合法構建模塊。
DTD 可以在 XML 文檔內聲明,也可以外部引用。
1,內部聲明:<!DOCTYPE 根元素 [元素聲明]> ex: <!DOCTYOE test [any]>
完整實(shí)例:
- <?xml version='1.0'?>
- <!DOCTYPE note [
- <!ELEMENT note (to,from,heading,body)>
- <!ELEMENT to (#PCDATA)>
- <!ELEMENT from (#PCDATA)>
- <!ELEMENT heading (#PCDATA)>
- <!ELEMENT body (#PCDATA)>
- ]>
- <note>
- <to>George</to>
- <from>John</from>
- <heading>Reminder</heading>
- <body>Don't forget the meeting!</body>
- </note>
2,外部聲明(引用外部DTD):<!DOCTYPE 根元素 SYSTEM '文件名'> ex:<!DOCTYPE test SYSTEM 'http://www.test.com/evil.dtd'>
完整實(shí)例:
- <?xml version='1.0'?>
- <!DOCTYPE note SYSTEM 'note.dtd'>
- <note>
- <to>George</to>
- <from>John</from>
- <heading>Reminder</heading>
- <body>Don't forget the meeting!</body>
- </note>
而note.dtd的內容為:
- <!ELEMENT note (to,from,heading,body)>
- <!ELEMENT to (#PCDATA)>
- <!ELEMENT from (#PCDATA)>
- <!ELEMENT heading (#PCDATA)>
- <!ELEMENT body (#PCDATA)>
DTD實(shí)體是用于定義引用普通文本或特殊字符的快捷方式的變量,可以?xún)炔柯暶骰?span>外部引用。
實(shí)體又分為一般實(shí)體和參數實(shí)體
1,一般實(shí)體的聲明語(yǔ)法:<!ENTITY 實(shí)體名 '實(shí)體內容“>
引用實(shí)體的方式:&實(shí)體名;
2,參數實(shí)體只能在DTD中使用,參數實(shí)體的聲明格式: <!ENTITY % 實(shí)體名 '實(shí)體內容“>
引用實(shí)體的方式:%實(shí)體名;
1,內部實(shí)體聲明:<!ENTITY 實(shí)體名稱(chēng) '實(shí)體的值'> ex:<!ENTITY eviltest 'eviltest'>
注意和DTD中的元素聲明區別<!ENTITY 聲明元素>
完整實(shí)例:
- <?xml version='1.0'?>
- <!DOCTYPE test [
- <!ENTITY writer 'Bill Gates'>
- <!ENTITY copyright 'Copyright W3School.com.cn'>
- ]>
- <test>&writer;©right;</test>
2,外部實(shí)體聲明:<!ENTITY 實(shí)體名稱(chēng) SYSTEM 'URI'>
完整實(shí)例:
- <?xml version='1.0'?>
- <!DOCTYPE test [
- <!ENTITY writer SYSTEM 'http://www.w3school.com.cn/dtd/entities.dtd'>
- <!ENTITY copyright SYSTEM 'http://www.w3school.com.cn/dtd/entities.dtd'>
- ]>
- <author>&writer;©right;</author>
在了解了基礎知識后,下面開(kāi)始了解xml外部實(shí)體注入引發(fā)的問(wèn)題。
1,何為XXE?
答: xxe也就是xml外部實(shí)體注入。也就是上文中加粗的那一部分。
2,怎樣構建外部實(shí)體注入?
方式一:直接通過(guò)DTD外部實(shí)體聲明
XML內容

方式二:通過(guò)DTD文檔引入外部DTD文檔,再引入外部實(shí)體聲明
XML內容:


方式三:通過(guò)DTD外部實(shí)體聲明引入外部實(shí)體聲明
好像有點(diǎn)拗口,其實(shí)意思就是先寫(xiě)一個(gè)外部實(shí)體聲明,然后引用的是在攻擊者服務(wù)器上面的外部實(shí)體聲明
具體看例子,XML內容

dtd文件內容:

3,支持的協(xié)議有哪些?
不同程序支持的協(xié)議如下圖:

其中php支持的協(xié)議會(huì )更多一些,但需要一定的擴展支持。

4,產(chǎn)生哪些危害?
XXE危害1:讀取任意文件


該CASE是讀取/etc/passwd,有些XML解析庫支持列目錄,攻擊者通過(guò)列目錄、讀文件,獲取賬號密碼后進(jìn)一步攻擊,如讀取tomcat-users.xml得到賬號密碼后登錄tomcat的manager部署webshell。
另外,數據不回顯就沒(méi)有問(wèn)題了嗎?如下圖,

不,可以把數據發(fā)送到遠程服務(wù)器,

遠程evil.dtd文件內容如下:

觸發(fā)XXE攻擊后,服務(wù)器會(huì )把文件內容發(fā)送到攻擊者網(wǎng)站

XXE危害2:執行系統命令

該CASE是在安裝expect擴展的PHP環(huán)境里執行系統命令,其他協(xié)議也有可能可以執行系統命令。
XXE危害3:探測內網(wǎng)端口


該CASE是探測192.168.1.1的80、81端口,通過(guò)返回的“Connection refused”可以知道該81端口是closed的,而80端口是open的。
XXE危害4:攻擊內網(wǎng)網(wǎng)站


該CASE是攻擊內網(wǎng)struts2網(wǎng)站,遠程執行系統命令。
方案一、使用開(kāi)發(fā)語(yǔ)言提供的禁用外部實(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ò)濾用戶(hù)提交的XML數據
關(guān)鍵詞:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC。
聯(lián)系客服