如何解决XML外部实体注入(XXE)漏洞

禁用XML处理器的外部实体解析功能是防范XXE漏洞最直接有效的方式,需在Java、.NET、Python等平台显式关闭DTD和外部实体解析,并规避危险API、加强输入验证、限制文件大小与嵌套深度,优先选用JSON等更安全的数据格式。

禁用XML处理器的外部实体解析功能,是防范XXE漏洞最直接有效的方式。

关闭DTD和外部实体解析

大多数XML解析器默认允许加载外部DTD并解析实体。必须显式关闭该功能:

  • Java(DOM/SAX/STAX):设置feature http://apache.org/xml/features/disallow-doctype-decl 为true;同时禁用 http://xml.org/sax/features/external-general-entitieshttp://xml.org/sax/features/external-parameter-entities
  • .NET:使用XmlReader.Create()时传入XmlReaderSettings,将DtdProcessing设为ProhibitXmlResolver设为null
  • Python(lxml):创建etree.XMLParser时设置resolve_entities=False,或使用forbid_dtd=True

避免使用危险的解析方式

某些解析方法天然易受XXE影响,应主动规避:

  • 不直接调用DocumentBuilder.parse(InputStream)等未配置防护的底层API
  • 禁用libxml2中的XML_PARSE_NOENTXML_PARSE_DTDLOAD标志(如PHP的libxml_disable_entity_loader(true)
  • 不依赖用户可控的XML Schema Location(xsi:schemaLocation)或DOCTYPE声明

输入验证与内容过滤

作为纵深防御手段,在解析前对XML做轻量级检查:

  • 用正则或简单字符串扫描拒绝含/font>、SYSTEMPUBLIC的关键字(注意绕过变体,如大小写混写、空格插入)
  • 若业务允许,仅接受白名单标签和属性,其余一律剥离或拒绝
  • 对上传或接收的XML,限制文件大小和嵌套深度,防止滥用实体展开导致的拒绝服务(Billion Laughs攻击)

使用更安全的数据格式替代

除非协议强制要求,否则优先选用JSON等无实体机制的格式:

  • Web API尽量用JSON通信,后端统一转为对象处理
  • 内部系统间交换结构化数据时,考虑Protocol Buffers或MessagePack
  • 确需XML时,采用简化子集(如RSS/Atom规范),并配合严格Schema校验(XSD)