XXE漏洞怎样彻底关闭?

wen 开源项目 85

本文目录导读:

XXE漏洞怎样彻底关闭?

  1. 核心原则:除非绝对必要,否则完全禁用外部实体解析
  2. 方案一:完全禁用外部实体(最彻底、最推荐)
  3. 方案二:加固过滤器(当必须使用外部实体时)
  4. 方案3:升级解析库与使用安全解析器
  5. 终极检查清单(逐项确认)

彻底关闭XXE漏洞,不能仅靠单一操作,而需要根据应用场景进行分层防御,以下是经过验证的彻底关闭方案,按优先级排序:

核心原则:除非绝对必要,否则完全禁用外部实体解析


完全禁用外部实体(最彻底、最推荐)

这是最安全的做法,如果业务根本不需要处理XML实体(例如仅仅是数据传输),直接禁用即可。

通用解析器配置(适用于大多数编程语言)

配置项 说明 示例
setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) 完全禁止DOCTYPE声明,这是最优先、最简单的开关,一旦开启,任何包含<!DOCTYPE的XML都会被拒绝。 Java: DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
setFeature("http://xml.org/sax/features/external-general-entities", false) 禁止解析外部普通实体(如 &xxe; 指向外部文件/URL)。 Python (lxml): parser = etree.XMLParser(resolve_entities=False, no_network=True)
setFeature("http://xml.org/sax/features/external-parameter-entities", false) 禁止解析外部参数实体%xxe;,常用于DTD中加载外部文件发起攻击)。 PHP (libxml): libxml_disable_entity_loader(true);new DOMDocument(['LIBXML_NOENT' => false, 'LIBXML_DTDLOAD' => false])

禁用外部实体加载(no_network / LIBXML_NONET

还需禁止解析器主动发起网络请求加载外部资源。

  • Java: 同样使用 setFeature,但禁用了general-entitiesparameter-entities后,网络请求也被阻止。
  • Python: parser = etree.XMLParser(no_network=True) 禁止从URL加载DTD或实体。
  • C# (.NET): 设置 XmlReaderSettings.DtdProcessing = DtdProcessing.Prohibit (彻底禁用DTD处理)。
  • PHP: libxml_disable_entity_loader(true); 会禁用从外部加载资源。注意:PHP 8.0+ 中该函数已废弃,推荐直接使用 LIBXML_NOENTLIBXML_DTDLOAD 参数。

加固过滤器(当必须使用外部实体时)

如果业务确实需要解析外部实体(例如引用内网配置文件),上述禁用方案会破坏业务,此时需要白名单+输入验证

  1. 禁用 SYSTEMPUBLIC 标识符:如果业务只需要解析内部定义的实体(如 &lt;),禁止使用外部来源。

    • 在代码级别,检查输入的XML是否包含 SYSTEMPUBLIC
    • 若包含 <!ENTITY xxe SYSTEM "..."<!ENTITY % xxe PUBLIC "...",直接拒绝请求。
  2. 禁用 file:// / expect:// 等危险协议

    • 配置白名单,只允许特定协议(如 http://, https:// 指向内部特定服务)。
    • 明确禁止:file://, expect://, php://, jar://, gopher://, data:// 等。
  3. 限制外部资源来源

    • 如果必须允许加载外部DTD,将来源限制为内部已知的、安全的服务器IP或域名
    • 使用网络级别的防火墙或代理,拦截解析器发出的、未经授权的DNS或HTTP请求。

方案3:升级解析库与使用安全解析器

旧版本的解析器(如 Java 1.8 以下的 DocumentBuilderFactory、老版 libxml2)默认配置不安全。

  • 升级版本:确保你使用的XML解析库是最新稳定版,现代库(如 Java 11+ 的 DOM、SAX、StAX;Python 3.x 的 xml.etree.ElementTree;PHP 8.0+ 的 libxml2)在默认配置下,部分实体解析已被禁用,但仍需显式禁用以杜绝漏网之鱼。
  • 使用安全解析器
    • Java:推荐使用 XMLInputFactory (StAX) 或 SAXParserFactory,通过上述setFeature进行配置。
    • Python:默认的 xml.etree.ElementTree 较安全,不解析外部实体,但使用 lxml 时,需手动设置 resolve_entities=False
    • .NET:从 .NET Framework 4.5.2 开始,默认 XmlReader 不再解析外部实体。:如果使用 XDocument.Load 且未传入 XmlReaderSettings,可能仍存在风险。正确做法:始终传入 new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit, XmlResolver = null }

终极检查清单(逐项确认)

  1. 禁用DOCTYPEdisallow-doctype-decl=true(最优先)。
  2. 禁用外部实体external-general-entities=falseexternal-parameter-entities=false
  3. 禁用网络加载no_network=trueLIBXML_NONET
  4. 禁用DTD处理dtdProcessing=Prohibit(.NET特有)。
  5. 升级解析库:使用最新稳定版。
  6. 避免使用危险API
    • 少用 javax.xml.parsers.DocumentBuilder(若必须用,务必设置)。
    • 不用 XmlDocument.LoadXml() (C#) 而不带XmlReaderSettings
    • 不用 simplexml_load_file() (PHP) 而不禁用实体加载。

最彻底的方式:disallow-doctype-decl 设为 true

如果无法做到,则必须同时禁用外部实体解析、禁用外部网络请求,并拒绝 SYSTEM/PUBLIC 关键字。

抱歉,评论功能暂时关闭!