必须禁用外部实体并限制资源消耗,否则可能触发XXE或XML DoS攻击;应禁用DTD、设置解析深度与大小限制、关闭XInclude/XSLT,并优先使用JSON替代XML,结合XSD验证和隔离环境解析实现多层防护。

处理用户上传的XML文件时,必须禁用外部实体解析并限制解析器资源消耗,否则可能触发XXE(XML External Entity)攻击或XML DoS(如Billion Laughs、Quadratic Blowup)。
禁用外部实体和DTD解析
绝大多数XML解析器默认允许加载外部DTD和实体,这是XXE漏洞的根源。必须显式关闭相关功能:
- Java(JAXP):设置FEATURE_SECURE_PROCESSING为true,并禁用http://apache.org/xml/features/disallow-doctype-decl和http://xml.org/sax/features/external-general-entities
- Python(lxml):使用etree.XMLParser(resolve_entities=False, no_network=True),避免用etree.parse()直接读取用户输入
- PHP(libxml):调用libxml_disable_entity_loader(true),并在simplexml_load_string()前设置LIBXML_NOENT | LIBXML_DTDATTR
限制XML解析深度与大小
即使禁用DTD,恶意构造的嵌套结构仍可耗尽内存或引发栈溢出。需主动设限:
- 预检文件大小:上传前检查Content-Length或流式读取头几百字节,拒绝超1MB(按业务调整)的XML
- 设置解析器深度限制:如Python lxml支持max_element_depth=100;Java SAXParser可通过自定义EntityResolver拦截深层递归
- 禁用XInclude和XSLT:这些扩展功能易被滥用,除非明确需要,否则一律关闭
改用白名单格式替代通用XML
若业务只需交换结构化数据,优先考虑更安全的替代方案:
- 接受JSON而非XML:天然不支持实体、无命名空间歧义、解析器普遍更严格
- 若必须用XML,定义严格XSD并启用验证:只允许已知元素和属性,拒绝未声明内容
- 对上传文件做预处理:用正则或轻量解析器剥离DOCTYPE、、等危险节点,再交给主解析器
运行在隔离环境中解析
即便做了上述防护,仍建议将XML解析逻辑部署在资源受限的独立服务中:
- 使用容器(如Docker)限制CPU、内存、文件句柄数,防止OOM或进程卡死
- 设置超时:解析操作超过5秒强制中断,避免慢速DoS
- 日志记录原始XML哈希(如SHA-256)和解析结果摘要,便于事后审计异常样本
基本上就这些。核心是“不信任任何外部输入,不依赖默认配置,层层设防”。










