XML注入攻击是什么 如何预防

XML注入攻击核心风险在于外部实体(XXE)、DOCTYPE滥用及未过滤用户输入拼接,防护需禁用外部实体、避免拼接输入、白名单验证、优先改用JSON。

XML注入攻击是指攻击者通过向应用程序提交恶意构造的XML数据,干扰或操控XML解析器行为,从而实现读取敏感文件、执行远程请求(SSRF)、触发拒绝服务(DoS),甚至执行任意代码等危害。它不单是“插入标签”那么简单,核心风险常来自外部实体(XXE)、DOCTYPE滥用、未过滤的用户输入拼接进XML结构等环节。

关键风险点在哪

常见触发场景包括:

  • 用户输入直接拼接到XML字符串中再解析(如用doc.createTextNode(input)未转义)
  • XML解析器默认开启外部实体加载,且未禁用DOCTYPE声明
  • 后端接收XML请求(如SOAP、REST API中的application/xml)但未做输入净化
  • 使用老旧或配置宽松的解析库(如libxml 2.9以前版本、未设安全特性的JAXP默认实例)

必须做的四件事

防护不是靠“加一层过滤”,而是从设计到解析全程设防:

  • 禁用外部实体和DOCTYPE:这是防XXE的底线。Java中设置disallow-doctype-declexternal-general-entities=false;PHP调用libxml_disable_entity_loader(true);Python lxml启用no_network=True
  • 绝不拼接用户输入进XML文本节点或属性值:改用DOM API的createTextNode()或XMLWriter的WriteElementString()等安全方法,它们会自动转义>&等字符
  • 输入验证走白名单而非黑名单:比如手机号只允许数字和+/-,邮箱用标准正则校验;避免“过滤掉”这类易绕过的黑名单策略
  • 优先考虑换格式:如果不是强依赖XML(如遗留系统集成、SOAP服务),用JSON替代。它天然无实体、无DTD、解析器更轻量也更安全

开发时容易忽略的细节

有些坑看似小,却常导致防线失效:

  • 框架虽内置防护(如Spring Boot 2.3+默认禁XXE),但若手动创建DocumentBuilderFactory就可能绕过——必须显式配置安全特性
  • 日志或调试代码里把原始XML打印出来,可能意外暴露file:///etc/passwd这类读取结果
  • 测试用例只覆盖正常XML,没测 ]>&xxe;这类恶意载荷
  • 前端传来的XML已“看起来干净”,但后端二次解析时仍用不安全方式处理(比如用eval()innerHTML渲染)

基本上就这些。核心就三句话:别拼接、要禁外部实体、信不过的输入一律当毒药处理。安全不在功能多,而在每一步都守住边界。