XML实体扩展注入与防御方案
XML 实体扩展注入(也称为 "Billion Laughs" 攻击或 "XML Bomb")是一种通过恶意构造的 XML 实体实现 拒绝服务攻击(DoS) 的手段。攻击者利用 XML 解析器处理实体时的递归扩展机制,通过极小的 XML 数据触发指数级内存消耗,导致系统资源耗尽。
攻击原理
xml
<!DOCTYPE foo [<!ENTITY a "xxxxxxxxxx"> <!-- 10个字符 --><!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;"> <!-- 10×10 = 100字符 --><!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;"> <!-- 100×10 = 1000字符 --> ]> <foo>&c;</foo>
递归扩展:实体
&c;
展开为 10 个&b;
,每个&b;
展开为 10 个&a;
,最终生成10×10×10 = 1000
个字符(实际攻击中层级更深,可达 GB/TB 级数据)。内存爆炸:解析器在内存中展开实体,消耗大量资源。
修复方案
1. 禁用 DTD 处理(最彻底)
原理:DTD 是定义实体的来源,禁用后实体无法被声明或扩展。
代码示例:
java
// Java (DocumentBuilderFactory) DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // 禁用 DTD
2. 禁用外部实体 + 限制实体扩展
适用场景:需要保留 DTD 但避免恶意实体。
关键配置:
java
// Java dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); // 禁用外部通用实体 dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); // 禁用外部参数实体 dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); // 禁用外部 DTD dbf.setExpandEntityReferences(false); // 禁止展开实体引用
3. 启用安全处理模式(Secure Processing)
原理:启用解析器的内置安全限制(如实体数量、深度等)。
java
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
各语言修复示例
Python (lxml)
python
from lxml import etree# 安全配置:禁用实体和 DTD parser = etree.XMLParser(resolve_entities=False, # 禁用实体解析no_network=True, # 禁止网络访问load_dtd=False, # 不加载 DTDdtd_validation=False # 不验证 DTD ) xml_data = etree.parse(xml_source, parser)
C# (.NET)
csharp
XmlReaderSettings settings = new XmlReaderSettings {DtdProcessing = DtdProcessing.Prohibit, // 完全禁用 DTDXmlResolver = null // 禁用解析器(防止外部实体) }; using (XmlReader reader = XmlReader.Create(input, settings)) {// 安全解析 XML }
PHP (libxml)
php
libxml_disable_entity_loader(true); // 禁用实体加载 $dom = new DOMDocument(); $dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD); // 避免加载 DTD
防御最佳实践
输入过滤:
检查传入 XML 是否包含
<!DOCTYPE
或<!ENTITY
声明。
资源限制:
设置 XML 解析器的最大内存和解析时间阈值。
依赖库更新:
使用最新版 XML 解析库(如 Apache Xerces、libxml2),旧版本可能有默认安全缺陷。
替代数据格式:
在无需 XML 高级特性时,改用 JSON/YAML 等更安全的格式。
检测工具
静态分析:使用 Checkmarx、Fortify 扫描代码中的 XML 解析点。
动态测试:通过 Burp Suite 或 OWASP ZAP 发送恶意 XML 实体测试服务端响应。
💡 关键点:XML 实体扩展注入不同于 XXE(外部实体注入),但防御手段重叠。禁用 DTD 可同时防御两者。