System.Xml 安全注意事项

更新:November 2007

下面各节讨论在使用 System.Xml 组件时可能发生的安全问题类型以及为缓解这些威胁可以采取的措施。

说明:

System.Xml 组件依赖于 Microsoft .NET Framework 安全系统。本主题仅解决专门由 XML 类处理的安全问题。有关更多信息,请参见 .NET Framework 中的安全性

  • XmlResolver 类

  • XmlReader 和 XmlReaderSettings 类

  • XmlTextReader 类

  • XslCompiledTransform 类

  • Document Object Model

XmlResolver 类

XmlResolver 类用于解析资源。该类用于加载 XML 文档、解析外部资源(例如实体、DTD 或架构)以及导入或包含指令。.NET Framework 包括 XmlResolver 类的两种实现。

XmlUrlResolver 类是 System.Xml 命名空间中所有类的默认解析器。它支持 file:// 和 http:// 协议以及来自 WebRequest 类的请求。在许多情况下,如果未指定应用程序应使用的 XmlResolver 对象,将使用没有用户凭据的 XmlUrlResolver 对象来访问 XML 资源。

XmlSecureResolver 类通过包装 XmlResolver 对象并限制基础 XmlResolver 有权访问的资源,可以帮助保证另一个 XmlResolver 对象的安全。例如,XmlSecureResolver 类可以禁止访问特定的 Internet 站点或区域。

在使用 XmlResolver 类时,应考虑下列事项。

  • XmlResolver 对象可以包含敏感信息,例如可以用于访问和检索数据的用户凭据。在缓存 XmlResolver 对象时应小心,不应将 XmlResolver 对象传递给不可信的组件,因为不可信的组件可能会使用 XmlResolver 及其用户凭据来访问数据。

  • 如果您设计的类属性使用 XmlResolver 类,该属性应定义为只写属性。该属性可以用于指定要使用的 XmlResolver,但是不能用于返回 XmlResolver 对象。这样,将允许不可信的组件使用该类,但是不允许检索和直接使用 XmlResolver 对象。

  • 如果应用程序接受来自不可信代码的 XmlResolver 对象,不能假定传入 GetEntity 方法的 URI 与 ResolveUri 方法返回的 URI 相同。从 XmlResolver 类派生的类可以重写 GetEntity 方法,并且返回的数据可以不同于原始 URI 中包含的数据。

  • 应用程序可以通过实现由包装实现的 IStream 来限制读取的字节数,从而缓解对 GetEntity 方法的内存拒绝服务威胁。如果恶意代码尝试将无限大的字节流传递给 GetEntity 方法,这种方式有助于您应对这种情况。

XmlReader 和 XmlReaderSettings 类

实际上,所有 System.Xml 组件都是基于分析 XML 的概念构建的。例如,XmlDocument 类使用 XmlReader 类来分析文档并生成 XML 文档的内存中表示形式。

我们建议使用 Create 方法创建 XmlReader 对象。XmlReaderSettings 类指定要在 XmlReader 对象上启用的功能集。

限制文档和实体扩展大小

使用 XmlReader 的应用程序的内存使用量可能与分析的 XML 文档的大小有关。拒绝服务攻击的一种形式是提交过大的 XML 文档进行分析。

使用 XmlReader 时,通过设置 MaxCharactersInDocument 属性,您可以限制能够分析的文档大小。通过设置 MaxCharactersFromEntities 属性,您可以限制从扩展实体中生成的字符数。有关设置这些属性的示例,请参见相应的参考主题。

DTD 处理

DTD 处理可能会导致 DoS 的情况。例如,DTD 可能包含嵌套实体或复杂内容模型,可能需要很长的时间来处理。

默认情况下禁用 DTD 处理。XmlReader 遇到 DTD 数据时,将引发 XmlException

架构处理

默认情况下不设置 XmlReaderSettings 对象的 ProcessInlineSchemaProcessSchemaLocation 验证标志。这样,在处理来自不可信的源的 XML 数据时,可以帮助防止 XmlReader 受到基于架构的攻击。设置了这些标志后,XmlReaderSettings 对象的 XmlResolver 用于在 XmlReader 中解析实例文档中遇到的架构位置。如果 XmlResolver 属性设置为 null,即使设置了 ProcessInlineSchemaProcessSchemaLocation 验证标志,也不会解析架构位置。

在验证期间添加的架构将添加新类型,可以改变所验证的文档的验证结果。因此,只应从可信的源解析外部架构。

在高可用性方案中,针对对文档大部分实施标识约束的架构验证不可信的大 XML 文档时,我们建议禁用 ProcessIdentityConstraints 标志(默认情况下启用)。

外部资源

XML 数据可以包含对外部资源(例如架构文件)的引用。默认情况下,外部资源使用没有用户凭据的 XmlUrlResolver 对象进行解析。这意味着在默认情况下,可以访问任何不需要凭据的位置。通过执行下列操作之一,可以进一步保证安全:

共享 XmlReaderSettings 对象

XmlReaderSettings 对象可以包含敏感信息,例如用户凭据。不可信的组件可能会使用 XmlReaderSettings 对象及其用户凭据来创建 XmlReader 对象,以读取数据。在缓存 XmlReaderSettings 对象时,或在将 XmlReaderSettings 对象从一个组件传递到另一个组件时,应小心。

支持组件

数据处理

XML 数据可以包含大量属性、命名空间声明、嵌套元素等,需要大量的时间来处理。

  • 可以创建自定义 IStream 实现来限制所使用的输入大小并将此实现提供给 XmlReader 类。

  • 使用 ReadValueChunk 方法处理大的数据流。此方法一次读取少量的字符,而不是为整个值分配单个字符串。

XmlTextReader 类

XmlTextReader 类是 XmlReader 类的旧式实现。

DTD 处理

默认情况下启用 DTD 处理。要禁用 DTD 处理,请将 ProhibitDtd 属性设置为 true。

实体处理

默认情况下不展开常规实体。常规实体在调用 ResolveEntity 方法时展开。

外部资源

XML 数据可以包含对外部资源的引用(例如 DTD 引用)。默认情况下,外部资源使用没有用户凭据的 XmlUrlResolver 对象进行解析。

通过执行下列操作之一,可以进一步保证安全:

XslCompiledTransform 类

XslCompiledTransform 类是支持 XSLT 1.0 语法的 XSLT 处理器。通过此类可以使用 XSLT 样式表转换 XML 数据。

外部资源

样式表可以包含对外部资源(例如 xsl:import 或 xsl:include 元素或者 document() 函数)的引用。

默认情况下,XslCompiledTransform 类支持 xsl:import 或 xsl:include 元素。默认情况下,XslCompiledTransform 类禁用对 document() 函数的支持。XsltSettings 类用于启用 document() 函数。

LoadTransform 方法包括使用 XmlResolver 对象作为一个参数的重载。如果未指定 XmlResolver,将使用没有用户凭据的默认 XmlUrlResolver

通过执行下列操作之一,可以控制如何访问外部资源:

  • 使用 XmlSecureResolver 对象限制 XSLT 进程可以访问的资源。

  • 通过将 null 传递给 XmlResolver 参数,不允许 XSLT 进程打开任何外部资源。

脚本块

默认情况下,XslCompiledTransform 类不支持脚本块。脚本块使用 XsltSettings 类启用。只有要求脚本支持并且处于完全可信的环境下时,才应启用 XSLT 脚本。

扩展对象

扩展对象为 XSLT 转换添加编程功能。默认情况下启用此功能。如果扩展对象传递给 Transform 方法,将在 XSLT 转换中使用。

文档对象模型

因为文档对象模型 (DOM) 将所有数据缓存在内存中,如果使用不可信的数据并且担心受到拒绝服务攻击,不建议执行 DOM 操作(例如查询、编辑、在文档之间移动子树以及保存 DOM 对象)。另一种选择是设置对读入 DOM 的数据量的限制。要这样做,一种方式是创建自定义流实现来限制所使用的输入大小并使用此实现来加载 DOM 对象。

XmlDocument 对象可以包含敏感信息,例如嵌入式 XmlResolver 对象中的用户凭据。如果 XmlDocument.XmlResolver 属性设置为具有用户凭据的 XmlResolver 对象,不应缓存 XmlDocument 对象或将其传递给不可信的组件。不可信的组件可能会使用 DOM 对象以及嵌入式 XmlResolver 的用户凭据来访问和加载数据。

请参见

概念

System.Xml 编码指南