Skip to content

JEP 185: Restrict Fetching of External XML Resources | 限制获取外部 XML 资源

摘要

增强 JAXP API,以添加限制可用于获取外部资源的网络协议集的能力。

目标

定义标准属性以限制可用于获取外部资源的网络协议集。新属性应与现有的安全处理功能以及其他现有功能和属性无缝协作。

非目标

本提案专注于处理外部资源。不打算重塑现有的安全架构,也不打算更改已由实现支持但 API 中未指定的功能和属性。

动机

JAXP 的 安全处理功能 对 XML 处理器设置资源限制,以应对某些类型的拒绝服务攻击。然而,它并未限制获取外部资源的手段,这在尝试安全处理 XML 文档时也很有用。当前的 JAXP 实现支持可用于强制实施此类限制的实现特定属性,但需要一个标准的方法来完成此操作。

描述

JAXP 1.5 添加了三个新的 API 级别属性,以将外部连接限制为特定的命名协议:

  • javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD:可通过其访问外部 DTD 和外部实体引用的协议列表。

  • javax.xml.XMLConstants.ACCESS_EXTERNAL_SCHEMA:可通过其解析由 importinclude 元素的 schemaLocation 属性指定的外部架构引用的协议列表。

  • javax.xml.XMLConstants.ACCESS_EXTERNAL_STYLESHEET:可通过其解析在样式表构造(如处理指令、document() 函数、import 元素和 include 元素)中指定的外部引用的协议列表。

它还添加了三个相应的系统属性,为开发人员提供无需更改代码即可更改设置的能力:

  • javax.xml.accessExternalDTD 对应于 ACCESS_EXTERNAL_DTD

  • javax.xml.accessExternalSchema 对应于 ACCESS_EXTERNAL_SCHEMA

  • javax.xml.accessExternalStylesheet 对应于 ACCESS_EXTERNAL_STYLESHEET

最后,它允许在现有的配置文件 ${java.home}/lib/jaxp.properties 中设置上述属性,以便为 JDK 或 JRE 的所有调用定义行为。文件中条目的格式为 property-name=value,例如:

ini
javax.xml.accessExternalDTD=file,http

属性值

上述任何属性的值都是一个协议列表,用逗号分隔。协议 是 URI 的方案部分,或者在 JAR 协议的情况下,是 jar 加上用冒号分隔的方案部分。方案的语法为:

java
scheme = alpha *( alpha | digit | "+" | "-" | "." )
where alpha = a-z and A-Z.

JAR 协议的语法为:

shell
jar[:scheme]

包含关键字 jar 的协议不区分大小写。值中由 Character.isSpaceChar() 定义的任何空白都会被忽略。协议的示例包括 filehttpjar:file

默认值:是否默认限制连接是实现选择。选项包括:

  • 空字符串表示不允许访问;
  • 特定协议(如 file)表示仅允许通过该协议进行访问;
  • 关键字 all 表示允许通过所有协议进行访问。

当启用 FEATURE_SECURE_PROCESSING 时,建议实现默认限制外部连接,但这可能会为处理具有外部引用的 XML/XSD/XSL 的应用程序带来问题。

授予所有访问权限:关键字 all 授予使用所有协议的权限。例如,在 jaxp.properties 文件中设置 jdk.xml.accessExternalDTD=all 将允许系统像以前一样工作,不对如何获取外部资源施加任何限制。

通过 JAXP API 设置属性

可以通过 JAXP 工厂以如下方式设置 JAXP 属性:

java
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setAttribute(name, value);

SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
parser.setProperty(name, value);

XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(name, value);

SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage);
schemaFactory.setProperty(name, value);

TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(name, value);

范围和顺序

javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING 是包括 DOM、SAX、Schema 验证、XSLT 和 XPath 在内的 XML 处理器所需的一个特性。建议实现将与安全性相关的特性和属性与该特性相关联。当安全特性设置为 true 时,它要求实现将 XML 处理限制在实现限制之内。当设置为 false 时,它指示实现不受限制地处理 XML。对于 JAXP 1.5 中引入的新属性,建议当安全特性设置为 true 时,实现应限制外部连接;当设置为 false 时,允许完全访问。

jaxp.properties 文件中指定的属性会影响 JDK 或 JRE 的所有调用,并将覆盖默认值或可能已通过 FEATURE_SECURE_PROCESSING 设置的值。

系统属性(当设置时)将仅影响一次调用,并将覆盖默认设置或 jaxp.properties 中设置的值,或可能已通过 FEATURE_SECURE_PROCESSING 设置的值。

通过 JAXP 工厂或 SAXParser API 指定的 JAXP 属性将覆盖系统属性、jaxp.properties 文件以及 FEATURE_SECURE_PROCESSING 的设置。

在以下情况下,新的 JAXP 属性将不会对它们试图限制的构造产生任何影响:

  • 当在 SAX 或 DOM 解析器上设置了实体解析器,在 StAX 解析器上设置了 XML 解析器,或在转换器上设置了 URIResolver 时。

  • 当通过 SchemaFactory.newSchema() 方法显式创建模式时。

  • 当不需要外部资源时。例如,参考实现支持以下特性和属性,并可以按如下方式设置,以指示处理器不加载外部 DTD 或解析外部实体。

    http://apache.org/xml/features/disallow-doctype-decl            true
    http://apache.org/xml/features/nonvalidating/load-external-dtd  false
    http://xml.org/sax/features/external-general-entities           false
    http://xml.org/sax/features/external-parameter-entities         false

测试

将添加新的测试以测试每个场景。同时,还将发布 JAXP TCK 的新版本。

需要进行大量测试以评估是否可以将 JDK 配置为默认限制连接。

风险和假设

JAXP 1.5 规范未指定属性的默认值。由于兼容性影响和风险,JAXP 1.5 将最初与默认配置集成,不限制连接。

JAXP 1.5 规范要求在将 FEATURE_SECURE_PROCESSING 明确设置为 true 时,必须设置新属性以限制外部连接。设置 FEATURE_SECURE_PROCESSING 的应用程序可能会注意到不兼容的行为,因此可能需要设置新的 JAXP 属性以覆盖 FEATURE_SECURE_PROCESSING。

影响

  • 其他 JDK 组件:JAX-WS 直接受到影响。JAX-WS 需要使用新属性来确定是否要解析外部资源。根据我们的调查以及与其他 JDK 组件所有者的讨论,没有其他组件直接受到影响。

  • 兼容性:规范对兼容性没有影响。是否通过设置默认值来限制或不限制来保持兼容性,取决于实现。

  • I18n/L10n:需要翻译几条新的错误消息。

  • TCK:需要创建 JAXP TCK 的新版本。