FlawOpen

flawopen.com/XXE/Java XML 解析器安全

Java XXE:DocumentBuilderFactory 默认安全吗?

CWE-611: Improper Restriction of XML External Entity ReferenceJava XML 参考指南
简短回答:默认不会阻止外部访问

JDK 默认启用了一些安全处理限制,但 DOM 和 SAX 的默认配置不会阻止访问外部资源。因此,如果应用未明确限制,XML 仍可能触发文件或网络访问。第三方 JAXP Provider 替换内置解析器时,行为也可能不同。请配置实际使用的解析器,不能仅凭 Java 版本判断安全性。

不安全
DocumentBuilderFactory factory =
    DocumentBuilderFactory.newInstance();
DocumentBuilder builder =
    factory.newDocumentBuilder();
Document document = builder.parse(untrustedXml);

// Java 9+:显式启用 JAXP 限制。
// 缺少必需设置时应安全失败。
// 解析器默认可能允许外部访问。
已强化
DocumentBuilderFactory factory =
    DocumentBuilderFactory.newDefaultInstance();

// 不要使用真实文件或服务进行测试。
factory.setFeature(
    XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature(
    "http://apache.org/xml/features/"
    + "disallow-doctype-decl", true);
factory.setAttribute(
    XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setXIncludeAware(false);

// 大小限制需要单独配置。
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(untrustedXml);

为什么 DOM 应优先拒绝 DOCTYPE

解析器支持时,拒绝 DOCTYPE 可阻止处理 DTD 中定义的外部实体和实体声明。显式启用 FEATURE_SECURE_PROCESSING,并额外限制外部 DTD 访问;JDK 默认启用 FSP 不代表外部连接已被拒绝。除非确有需要,否则禁用 XInclude。若 Provider 不支持必需设置,应让解析器初始化失败,不能带着部分防护继续运行。

如果应用必须接受 DTD,也不要开放外部访问。禁用外部通用实体、参数实体和外部 DTD 加载;将 ACCESS_EXTERNAL_DTD 设为空字符串,并保留处理限制。setExpandEntityReferences(false) 只改变文档树表示,不能替代对外部资源的阻止。

分别强化每个 JAXP 处理器

XML 处理的总体策略相同,但各 API 的设置不同。检查 SAXParserFactory/XMLReader、StAX XMLInputFactory、TransformerFactory、SchemaFactory、Validator 和 JAXB。StAX 不支持 FEATURE_SECURE_PROCESSING;应使用其专属属性禁用 DTD 和外部实体。还要限制外部 Schema 和样式表。参考 OWASP 针对各 API 的示例,并确认实际 Provider。

不要把单个解析器设置视为 JVM 全局防护。JAXP Provider 查找可能选择第三方实现,组合处理器也可能创建内部解析器。请测试生产环境实际使用的运行时、Provider 和代码路径。

常见问题

FEATURE_SECURE_PROCESSING 默认会阻止外部实体吗?

如果只是默认启用,则不会。Oracle 文档说明默认 FSP 会应用处理限制,但在通过 API 显式启用 FSP 或设置外部访问属性之前,外部连接仍可能被允许。请明确设置策略并验证 Provider。

较新的 JDK 改变了默认值吗?

JDK 版本不断增加限制和处理上限,但 Oracle JAXP 指南仍区分默认 FSP 与显式拒绝外部访问。第三方 Provider 也可能不同。应显式配置所需控制,不依赖版本或 classpath 默认值。

有效文档确实需要 DTD 时怎么办?

尽量使用可信的本地目录或 resolver。如果必须处理 DTD,应阻止外部协议和实体加载,保留 JAXP 处理限制,并在不需要时禁用 XInclude。此策略比拒绝 DOCTYPE 更复杂,应使用确切 Provider 和合法文档进行测试。

来源与参考资料

另请参阅 XML 外部实体注入(XXE,CWE-611):原理与防御方法 — flawopen.com Python XML XXE 安全:ElementTree、Expat 与 lxml .NET XmlReader 能防御 XXE 吗?