XML外部实体(XXE)注入攻击详解
字数 1191 2025-11-09 13:44:41
XML外部实体(XXE)注入攻击详解
1. 基本概念
XML外部实体(XXE)注入是一种针对XML处理程序的漏洞,攻击者通过篡改XML输入,使解析器加载恶意外部实体(如本地文件、远程资源),导致信息泄露、内网探测甚至命令执行。其根源在于XML标准支持外部实体引用功能,而配置不当的解析器会直接执行该功能。
2. XML外部实体的工作原理
XML文档可定义两种实体:
- 内部实体:值直接嵌入XML,如
<!ENTITY name "value">。 - 外部实体:值来自外部资源,格式为
<!ENTITY name SYSTEM "file:///etc/passwd">。
解析器遇到&name;时,会自动替换为对应资源内容。例如:
<?xml version="1.0"?>
<!DOCTYPE data [
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<user>&file;</user>
若解析器未禁用外部实体,会返回 /etc/passwd 的文件内容。
3. 攻击场景与利用方式
(1)文件读取
- 通过
file://协议读取服务器本地文件(如系统配置文件、源代码)。 - 注意:某些解析器可能限制文件路径字符(如Java的
file://需用file:///)。
(2)内网探测(SSRF)
- 利用
http://协议请求内网资源,通过响应时间或错误信息判断服务是否存在:
<!ENTITY ssrf SYSTEM "http://192.168.1.1:8080/">
(3)拒绝服务(DoS)
- 使用“亿级实体膨胀”(Billion Laughs Attack):通过嵌套实体引用消耗内存:
<!ENTITY a "a">
<!ENTITY b "&a;&a;&a;&a;">
<!ENTITY c "&b;&b;&b;&b;">
4. 漏洞产生的条件
- 使用易受攻击的XML解析器(如旧版libxml2、Java SAXParser等)。
- 解析器默认启用外部实体加载(如PHP的LIBXML_NOENT选项未设置)。
- 用户输入直接拼接到XML中且未过滤。
5. 防御措施
(1)禁用外部实体
- PHP:
libxml_disable_entity_loader(true); - Java:设置
SAXParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)。 - Python:使用
defusedxml库替代标准库。
(2)白名单验证
- 对用户输入的XML结构进行校验,过滤
<!DOCTYPE>和<!ENTITY>声明。
(3)使用数据格式替代XML
- 优先选择JSON等更简单的数据格式,避免XML复杂性带来的风险。
6. 实际案例
- 2014年 WhatsApp XXE漏洞:攻击者通过恶意视频文件触发XML解析,读取设备文件。
- 2017年 WordPress XXE:插件中的RSS解析功能未禁用外部实体,导致服务器文件泄露。
总结
XXE漏洞的危害程度取决于解析器配置和服务器环境。防御核心在于严格配置XML解析器(禁用外部实体、禁用DTD)并对输入内容进行约束。