数据集和 DataTable 安全指南DataSet and DataTable security guidance

本文适用于:This article applies to:

  • .NET Framework(所有版本).NET Framework (all versions)
  • .NET Core 和更高版本.NET Core and later
  • .NET 5.0 及更高版本.NET 5.0 and later

数据集DataTable类型是旧的 .net 组件,可将数据集表示为托管对象。The DataSet and DataTable types are legacy .NET components that allow representing data sets as managed objects. 这些组件在 .NET Framework 1.0 中引入,作为原始 ADO.NET 基础结构的一部分。These components were introduced in .NET Framework 1.0 as part of the original ADO.NET infrastructure. 其目标是通过关系数据集提供托管视图,并将数据的基础数据源抽象到 XML、SQL 或其他技术。Their goal was to provide a managed view over a relational data set, abstracting away whether the underlying source of the data was XML, SQL, or another technology.

有关 ADO.NET 的详细信息,包括更多新式数据视图模式,请参阅 ADO.NET 文档For more information on ADO.NET, including more modern data view paradigms, see the ADO.NET documentation.

从 XML 反序列化数据集或 DataTable 时的默认限制Default restrictions when deserializing a DataSet or DataTable from XML

在所有受支持版本的 .NET Framework、.NET Core 和 .NET 上, DataSet 并对 DataTable 可能存在于反序列化数据中的对象类型施加以下限制。On all supported versions of .NET Framework, .NET Core, and .NET, DataSet and DataTable place the following restrictions on what types of objects may be present in the deserialized data. 默认情况下,此列表限制为:By default, this list is restricted to:

  • 基元和基元等效项:、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、 bool char sbyte byte short ushort int uint long ulong float double decimal DateTime DateTimeOffset TimeSpan string Guid SqlBinary SqlBoolean SqlByte SqlBytes SqlChars SqlDateTime SqlDecimal SqlDouble SqlGuid SqlInt16 SqlInt32 SqlInt64 SqlMoney SqlSingleSqlStringPrimitives and primitive equivalents: bool, char, sbyte, byte, short, ushort, int, uint, long, ulong, float, double, decimal, DateTime, DateTimeOffset, TimeSpan, string, Guid, SqlBinary, SqlBoolean, SqlByte, SqlBytes, SqlChars, SqlDateTime, SqlDecimal, SqlDouble, SqlGuid, SqlInt16, SqlInt32, SqlInt64, SqlMoney, SqlSingle, and SqlString.
  • 常用的非基元: TypeUriBigIntegerCommonly used non-primitives: Type, Uri, and BigInteger.
  • 常用的 系统 类型: ColorPointPointF 、、、 Rectangle RectangleF SizeSizeFCommonly used System.Drawing types: Color, Point, PointF, Rectangle, RectangleF, Size, and SizeF.
  • Enum 各种.Enum types.
  • 上述类型的数组和列表。Arrays and lists of the above types.

如果传入的 XML 数据包含其类型不在此列表中的对象:If the incoming XML data contains an object whose type is not in this list:

  • 使用以下消息和堆栈跟踪引发异常。An exception is thrown with the following message and stack trace. 此处不允许出现错误消息: "InvalidOperationException: Type" <Type Name> 、Version = <n.n.n.n> 、Culture = <culture> 、PublicKeyToken = <token value> '。Error Message: System.InvalidOperationException : Type '<Type Name>, Version=<n.n.n.n>, Culture=<culture>, PublicKeyToken=<token value>' is not allowed here. https://go.microsoft.com/fwlink/?linkid=2132227有关更多详细信息,请参阅。See https://go.microsoft.com/fwlink/?linkid=2132227 for more details. Stack 跟踪:在 TypeLimiter. EnsureTypeIsAllowed (Type type,TypeLimiter capturedLimiter) 在 (Type,UpdateColumnType StorageType) ,System.Data.DataColumn.set_DataType (类型值) Stack Trace: at System.Data.TypeLimiter.EnsureTypeIsAllowed(Type type, TypeLimiter capturedLimiter) at System.Data.DataColumn.UpdateColumnType(Type type, StorageType typeCode) at System.Data.DataColumn.set_DataType(Type value)

  • 反序列化操作失败。The deserialization operation fails.

将 XML 加载到现有的 DataSetDataTable 实例时,也会考虑现有的列定义。When loading XML into an existing DataSet or DataTable instance, the existing column definitions are also taken into account. 如果表已包含自定义类型的列定义,则在 XML 反序列化操作期间,该类型暂时添加到允许列表中。If the table already contains a column definition of a custom type, that type is temporarily added to the allow list for the duration of the XML deserialization operation.

备注

向添加列后 DataTableReadXml 将不会从 XML 读取架构,如果架构不匹配,也不会读取记录,因此,你需要自行添加所有列以使用此方法。Once you add columns to a DataTable, ReadXml will not read the schema from the XML, and if the schema does not match it will also not read in the records, so you will need to add all the columns yourself to use this method.

XmlReader xmlReader = GetXmlReader();

// Assume the XML blob contains data for type MyCustomClass.
// The following call to ReadXml fails because MyCustomClass isn't in the allowed types list.

DataTable table = new DataTable("MyDataTable");
table.ReadXml(xmlReader);

// However, the following call to ReadXml succeeds, since the DataTable instance
// already defines a column of type MyCustomClass.

DataTable table = new DataTable("MyDataTable");
table.Columns.Add("MyColumn", typeof(MyCustomClass));
table.ReadXml(xmlReader); // this call will succeed

当使用 XmlSerializer 反序列化或的实例时,对象类型限制也适用 DataSet DataTableThe object type restrictions also apply when using XmlSerializer to deserialize an instance of DataSet or DataTable. 但是,当使用 BinaryFormatter 反序列化或的实例时,它们可能不适用 DataSet DataTableHowever, they may not apply when using BinaryFormatter to deserialize an instance of DataSet or DataTable.

使用时,不应用对象类型限制 DataAdapter.Fill ,例如,在 DataTable 不使用 XML 反序列化 api 的情况下直接从数据库填充实例时。The object type restrictions don't apply when using DataAdapter.Fill, such as when a DataTable instance is populated directly from a database without using the XML deserialization APIs.

扩展允许的类型列表Extend the list of allowed types

除了上面列出的内置类型外,应用程序还可以扩展允许的类型列表以包括自定义类型。An app can extend the allowed types list to include custom types in addition to the built-in types listed above. 如果扩展允许的类型列表,则更改会 all 影响 DataSet DataTable 应用内的所有和实例。If extending the allowed types list, the change affects all DataSet and DataTable instances within the app. 不能从内置允许类型列表中删除类型。Types cannot be removed from the built-in allowed types list.

通过配置 ( 扩展 .NET Framework 4.0-4.8) Extend through configuration (.NET Framework 4.0 - 4.8)

App.config 可用于扩展允许的类型列表。App.config can be used to extend the allowed types list. 扩展允许的类型列表:To extend the allowed types list:

  • 使用 <configSections> 元素可添加对 " system.object 配置" 部分的引用。Use the <configSections> element to add a reference to the System.Data configuration section.
  • 使用 <system.data.dataset.serialization> / <allowedTypes> 指定其他类型。Use <system.data.dataset.serialization>/<allowedTypes> to specify additional types.

每个 <add> 元素只能使用其程序集限定类型名称指定一种类型。Each <add> element must specify only one type by using its assembly qualified type name. 若要将其他类型添加到 "允许的类型" 列表中,请使用多个 <add> 元素。To add additional types to the allowed types list, use multiple <add> elements.

下面的示例演示如何通过添加自定义类型来扩展允许的类型列表 Fabrikam.CustomTypeThe following sample shows extending the allowed types list by adding the custom type Fabrikam.CustomType.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="system.data.dataset.serialization" type="System.Data.SerializationSettingsSectionGroup, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <section name="allowedTypes" type="System.Data.AllowedTypesSectionHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    </sectionGroup>
  </configSections>
  <system.data.dataset.serialization>
    <allowedTypes>
      <!-- <add type="assembly qualified type name" /> -->
      <add type="Fabrikam.CustomType, Fabrikam, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2b3831f2f2b744f7" />
      <!-- additional <add /> elements as needed -->
    </allowedTypes>
  </system.data.dataset.serialization>
</configuration>

若要检索某个类型的程序集限定名称,请使用 AssemblyQualifiedName 属性,如以下代码所示。To retrieve the assembly qualified name of a type, use the Type.AssemblyQualifiedName property, as demonstrated in the following code.

string assemblyQualifiedName = typeof(Fabrikam.CustomType).AssemblyQualifiedName;

通过配置 ( 扩展 .NET Framework 2.0-3.5) Extend through configuration (.NET Framework 2.0 - 3.5)

如果你的应用面向 .NET Framework 2.0 或3.5,你仍可以使用上述 App.config 机制来扩展允许的类型列表。If your app targets .NET Framework 2.0 or 3.5, you can still use the above App.config mechanism to extend the allowed types list. 但是,你 <configSections> 的元素看上去将略有不同,如以下代码所示:However, your <configSections> element will look slightly different, as shown in the following code:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <!-- The below <sectionGroup> and <section> are specific to .NET Framework 2.0 and 3.5. -->
    <sectionGroup name="system.data.dataset.serialization" type="System.Data.SerializationSettingsSectionGroup, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <section name="allowedTypes" type="System.Data.AllowedTypesSectionHandler, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    </sectionGroup>
  </configSections>
  <system.data.dataset.serialization>
    <allowedTypes>
      <!-- <add /> elements, as demonstrated in the .NET Framework 4.0 - 4.8 sample code above. -->
    </allowedTypes>
  </system.data.dataset.serialization>
</configuration>

以编程方式扩展 ( .NET Framework,.NET Core,.NET 5.0 +) Extend programmatically (.NET Framework, .NET Core, .NET 5.0+)

还可以通过将 DataSetDefaultAllowedTypes 与众所周知的密钥系统 一起使用,以编程方式扩展允许的类型列表,如下面的代码所示。The list of allowed types can also be extended programmatically by using AppDomain.SetData with the well-known key System.Data.DataSetDefaultAllowedTypes, as shown in the following code.

Type[] extraAllowedTypes = new Type[]
{
    typeof(Fabrikam.CustomType),
    typeof(Contoso.AdditionalCustomType)
};

AppDomain.CurrentDomain.SetData("System.Data.DataSetDefaultAllowedTypes", extraAllowedTypes);

如果使用扩展机制,则与密钥 DataSetDefaultAllowedTypes 关联的值的类型必须为 Type[]If using the extension mechanism, the value associated with the key System.Data.DataSetDefaultAllowedTypes must be of type Type[].

在 .NET Framework 上,可以使用 App.config 和来扩展允许的类型列表 AppDomain.SetDataOn .NET Framework, the list of allowed types may be extended both with App.config and AppDomain.SetData. 在这种情况下, DataSetDataTable 将允许将对象作为数据的一部分进行反序列化(如果其类型存在于任一列表中)。In this case, DataSet and DataTable will allow an object to be deserialized as part of the data if its type is present in either list.

在审核模式下运行应用 ( .NET Framework) Run an app in audit mode (.NET Framework)

在 .NET Framework 中, DataSetDataTable 提供审核模式功能。In .NET Framework, DataSet and DataTable provide an audit mode capability. 当启用审核模式时, DataSetDataTable 根据允许的类型列表比较传入对象的类型。When audit mode is enabled, DataSet and DataTable compare the types of incoming objects against the allowed types list. 但是,如果显示不允许其类型的对象,则 会引发异常。However, if an object whose type is not allowed is seen, an exception is not thrown. 相反, DataSetDataTable 通知任何附加的 TraceListener 实例存在可疑类型,从而允许 TraceListener 记录此信息。Instead, DataSet and DataTable notify any attached TraceListener instances that a suspicious type is present, allowing the TraceListener to log this information. 不会引发异常,并且反序列化操作将继续。No exception is thrown and the deserialization operation continues.

警告

在 "审核模式" 下运行应用程序时,只应使用临时度量值进行测试。Running an app in "audit mode" should only be a temporary measure used for testing. 当启用审核模式时, DataSet 并且 DataTable 不强制实施类型限制,这可能会在应用内引入安全漏洞。When audit mode is enabled, DataSet and DataTable do not enforce type restrictions, which can introduce a security hole inside your app. 有关详细信息,请参阅标题为删除不受信任输入相关的所有类型限制和安全性部分。For more information, see the sections titled Removing all type restrictions and Safety with regard to untrusted input.

可以通过 App.config 启用审核模式:Audit mode can be enabled through App.config:

  • 请参阅本文档中的 扩展配置 部分,了解要为元素放入的适当值 <configSections>See the Extending through configuration section in this document for information on the proper value to put for the <configSections> element.
  • 使用 <allowedTypes auditOnly="true"> 启用审核模式,如以下标记所示。Use <allowedTypes auditOnly="true"> to enable audit mode, as shown in the following markup.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <!-- See the section of this document titled "Extending through configuration" for the appropriate
         <sectionGroup> and <section> elements to put here, depending on whether you're running .NET
         Framework 2.0 - 3.5 or 4.0 - 4.8. -->
  </configSections>
  <system.data.dataset.serialization>
    <allowedTypes auditOnly="true"> <!-- setting auditOnly="true" enables audit mode -->
      <!-- Optional <add /> elements as needed. -->
    </allowedTypes>
  </system.data.dataset.serialization>
</configuration>

一旦启用了审核模式,就可以使用 App.config 将您首选的内置 TraceListener DataSet TraceSource. 跟踪 System.Data.DataSet 源名称连接到 "system.string"。Once audit mode is enabled, you can use App.config to connect your preferred TraceListener to the DataSet built-in TraceSource. The name of the built-in trace source is System.Data.DataSet. 下面的示例演示如何将跟踪事件写入控制台 磁盘上的日志文件。The following sample demonstrates writing trace events to the console and to a log file on disk.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="System.Data.DataSet"
              switchType="System.Diagnostics.SourceSwitch"
              switchValue="Warning">
        <listeners>
          <!-- write to the console -->
          <add name="console"
               type="System.Diagnostics.ConsoleTraceListener" />
          <!-- *and* write to a log file on disk -->
          <add name="filelog"
               type="System.Diagnostics.TextWriterTraceListener"
               initializeData="c:\logs\mylog.txt" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
</configuration>

有关和的详细 TraceSource 信息 TraceListener ,请参阅文档 如何:将 TraceSource 和筛选器与跟踪侦听器一起使用For more information on TraceSource and TraceListener, see the document How to: Use TraceSource and Filters with Trace Listeners.

备注

在审核模式下运行应用在 .NET Core 或 .NET 5.0 及更高版本中不可用。Running an app in audit mode is not available in .NET Core or in .NET 5.0 and later.

删除所有类型限制Remove all type restrictions

如果应用必须从和中移除所有类型限制 DataSet 限制 DataTableIf an app must remove all type limiting restrictions from DataSet and DataTable:

  • 有几个选项可用于取消类型限制限制。There are several options to suppress type limiting restrictions.
  • 可用的选项取决于应用的目标框架。The options available depend on the framework the app targets.

警告

删除所有类型限制可能会在应用内引入安全漏洞。Removing all type restrictions can introduce a security hole inside the app. 使用此机制时,请确保应用 使用 DataSetDataTable 读取不受信任的输入。When using this mechanism, ensure the app does not use DataSet or DataTable to read untrusted input. 有关详细信息,请参阅 CVE-2020-1147 和标题为 " 有关不受信任的输入的安全" 的部分。For more information, see CVE-2020-1147 and the following section titled Safety with regard to untrusted input.

通过 AppContext 配置 ( .NET Framework 4.6-4.8、.NET Core 2.1 及更高版本、.NET 5.0 和更高版本) Through AppContext configuration (.NET Framework 4.6 - 4.8, .NET Core 2.1 and later, .NET 5.0 and later)

AppContext Switch.System.Data.AllowArbitraryDataSetTypeInstantiation 当设置为时,开关会 true 从和中移除所有类型限制限制 DataSet DataTableThe AppContext switch, Switch.System.Data.AllowArbitraryDataSetTypeInstantiation, when set to true removes all type limiting restrictions from DataSet and DataTable.

在 .NET Framework 中,可以通过 App.config 启用此开关,如以下配置所示:In .NET Framework, this switch can be enabled via App.config, as shown in the following configuration:

<configuration>
   <runtime>
      <!-- Warning: setting the following switch can introduce a security problem. -->
      <AppContextSwitchOverrides value="Switch.System.Data.AllowArbitraryDataSetTypeInstantiation=true" />
   </runtime>
</configuration>

在 ASP.NET 中, <AppContextSwitchOverrides> 元素不可用。In ASP.NET, the <AppContextSwitchOverrides> element is not available. 相反,可以通过 Web.config 启用交换机,如以下配置所示:Instead, the switch can be enabled via Web.config, as shown in the following configuration:

<configuration>
    <appSettings>
        <!-- Warning: setting the following switch can introduce a security problem. -->
        <add key="AppContext.SetSwitch:Switch.System.Data.AllowArbitraryDataSetTypeInstantiation" value="true" />
    </appSettings>
</configuration>

有关详细信息,请参阅 <AppContextSwitchOverrides> 元素。For more information, see the <AppContextSwitchOverrides> element.

在 .NET Core、.NET 5 和 ASP.NET Core 中,此设置由 runtimeconfig.js 控制,如以下 JSON 中所示:In .NET Core, .NET 5, and ASP.NET Core, this setting is controlled by runtimeconfig.json, as shown in the following JSON:

{
  "runtimeOptions": {
    "configProperties": {
      "Switch.System.Data.AllowArbitraryDataSetTypeInstantiation": true
    }
  }
}

有关详细信息,请参阅 ".Net Core 运行时配置设置"For more information, see ".NET Core run-time configuration settings".

AllowArbitraryDataSetTypeInstantiation 还可以通过 AppContext (而不是配置文件)以编程方式进行设置,如以下代码所示:AllowArbitraryDataSetTypeInstantiation can also be set programmatically via AppContext.SetSwitch instead of using a configuration file, as shown in the following code:

// Warning: setting the following switch can introduce a security problem.
AppContext.SetSwitch("Switch.System.Data.AllowArbitraryDataSetTypeInstantiation", true);

如果选择前面的编程方法,则对的调用 AppContext.SetSwitch 应在应用程序启动初期进行。If you choose the preceding programmatic approach, the call to AppContext.SetSwitch should occur early in the apps startup.

通过计算机范围内的注册表 ( .NET Framework 2.0-4.8) Through the machine-wide registry (.NET Framework 2.0 - 4.8)

如果不可用 AppContext ,则可以使用 Windows 注册表禁用类型限制检查:If AppContext is not available, type limiting checks can be disabled with the Windows registry:

  • 管理员必须配置注册表。An administrator must configure the registry.
  • 使用注册表是计算机范围的更改,将影响计算机上运行的 所有 应用。Using the registry is a machine-wide change and will affect all apps running on the machine.
类型Type ValueValue
注册表项Registry key HKLM\SOFTWARE\Microsoft\.NETFramework\AppContext
值名称Value name Switch.System.Data.AllowArbitraryDataSetTypeInstantiation
值类型Value type REG_SZ
值数据Value data true

在64位操作系统中,需要为上面显示的64位密钥 (添加此值) 和32位密钥。On a 64-bit operating system, this value my need to be added for both the 64-bit key (shown above) and the 32-bit key. 32位键位于 HKLM\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\AppContextThe 32-bit key is located at HKLM\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\AppContext.

有关使用注册表进行配置的详细信息 AppContext ,请参阅 "库使用者的 AppContext"For more information on using the registry to configure AppContext, see "AppContext for library consumers".

不受信任输入相关的安全Safety with regard to untrusted input

尽管 DataSetDataTable 确实对允许在反序列化 XML 有效负载时存在的类型施加默认限制,但 DataSet DataTable 在使用不受信任的输入进行填充时,和都是不安全的。While DataSet and DataTable do impose default limitations on the types that are allowed to be present while deserializing XML payloads, DataSet and DataTable are in general not safe when populated with untrusted input. 下面是 DataSetDataTable 实例可能读取不受信任的输入的一系列非详尽列表。The following is a non-exhaustive list of ways that a DataSet or DataTable instance might read untrusted input.

  • DataAdapter引用数据库, DataAdapter.Fill 方法用于使用 DataSet 数据库查询的内容来填充。A DataAdapter references a database, and the DataAdapter.Fill method is used to populate a DataSet with the contents of a database query.
  • DataSet.ReadXmlDataTable.ReadXml 方法用于读取包含列和行信息的 XML 文件。The DataSet.ReadXml or DataTable.ReadXml method is used to read an XML file containing column and row information.
  • DataSetDataTable 实例序列化为 ASP.NET (SOAP) web 服务或 WCF 终结点。A DataSet or DataTable instance is serialized as part of a ASP.NET (SOAP) web services or WCF endpoint.
  • 序列化程序(如) XmlSerializer 用于 DataSet 从 XML 流反序列化或 DataTable 实例。A serializer such as XmlSerializer is used to deserialize a DataSet or DataTable instance from an XML stream.
  • 序列化程序(如) JsonConvert 用于 DataSet 从 JSON 流反序列化或 DataTable 实例。A serializer such as JsonConvert is used to deserialize a DataSet or DataTable instance from a JSON stream. JsonConvert 是常用的第三方 Newtonsoft.Js 库中的一种方法。JsonConvert is a method in the popular third-party Newtonsoft.Json library.
  • 序列化程序(如) BinaryFormatter 用于 DataSet DataTable 从原始字节流中反序列化或实例。A serializer such as BinaryFormatter is used to deserialize a DataSet or DataTable instance from a raw byte stream.

本文档讨论上述方案的安全注意事项。This document discusses safety considerations for the preceding scenarios.

用于 DataAdapter.Fill DataSet 从不受信任的数据源填充Use DataAdapter.Fill to populate a DataSet from an untrusted data source

DataSet DataAdapter 通过使用 DataAdapter.Fill 方法,可以从中填充实例,如下面的示例中所示。A DataSet instance can be populated from a DataAdapter by using the DataAdapter.Fill method, as shown in the following example.

// Assumes that connection is a valid SqlConnection object.
string queryString =
  "SELECT CustomerID, CompanyName FROM dbo.Customers";
SqlDataAdapter adapter = new SqlDataAdapter(queryString, connection);

DataSet customers = new DataSet();
adapter.Fill(customers, "Customers");

(上面的代码示例是 从 DataAdapter 填充数据集中找到的更大示例的一部分。 ) (The code sample above is part of a larger sample found at Populating a DataSet from a DataAdapter.)

大多数应用程序都可以简化,并假定其数据库层受信任。Most apps can simplify and assume that their database layer is trusted. 但是,如果您正在对应用程序进行 威胁建模 ,则威胁模型可能会将应用程序 (客户端) 和数据库层之间的信任边界视为 (服务器) 。However, if you are in the habit of threat modeling your apps, your threat model may consider there to be a trust boundary between the application (client) and database layer (server). 在客户端和服务器之间使用 相互身份验证AAD 身份验证 是一种帮助解决与此相关的风险的方法。Using mutual authentication or AAD authentication between client and server is one way to help address the risks associated with this. 本部分的剩余部分讨论连接到不受信任的服务器的客户端可能的结果。The remainder of this section discusses the possible result of a client connecting to an untrusted server.

指向 DataAdapter 不受信任的数据源的后果取决于 DataAdapter 其自身的实现。The consequences of pointing a DataAdapter at an untrusted data source depend on the implementation of the DataAdapter itself.

SqlDataAdapterSqlDataAdapter

对于内置类型 SqlDataAdapter,引用不受信任的数据源可能会导致拒绝服务 (DoS) 攻击。For the built-in type SqlDataAdapter, referencing an untrusted data source could result in a denial of service (DoS) attack. DoS 攻击可能导致应用变得无响应或崩溃。The DoS attack could result in the app becoming unresponsive or crashing. 如果攻击者可以在应用程序中使用 DLL,则他们还可以实现本地代码执行。If an attacker can plant a DLL alongside the app, they may also be able to achieve local code execution.

其他 DataAdapter 类型Other DataAdapter types

第三方 DataAdapter 实现必须对其在不受信任的输入中提供的安全保证进行自我评估。Third-party DataAdapter implementations must make their own assessments about what security guarantees they provide in the face of untrusted inputs. .NET 无法确保与这些实现有关的任何安全保障。.NET cannot make any safety guarantees regarding these implementations.

ReadXml 和 ReadXmlDataSet.ReadXml and DataTable.ReadXml

DataSet.ReadXml DataTable.ReadXml 与不受信任的输入一起使用时,和方法是安全的。The DataSet.ReadXml and DataTable.ReadXml methods are not safe when used with untrusted input. 强烈建议使用者改为考虑使用本文档后面所述的备选方案之一。We strongly recommend that consumers instead consider using one of the alternatives outlined later in this document.

和的实现 DataSet.ReadXml DataTable.ReadXml 最初是在序列化漏洞成为一种很好理解的威胁类别之前创建的。The implementations of DataSet.ReadXml and DataTable.ReadXml were originally created before serialization vulnerabilities were a well-understood threat category. 因此,代码不遵循当前安全最佳做法。As a result, the code does not follow current security best practices. 这些 Api 可用作攻击者对 web 应用执行 DoS 攻击的媒介。These APIs can be used as vectors for attackers to perform DoS attacks against web apps. 这些攻击可能会导致 web 服务无响应或导致意外的进程终止。These attacks might render the web service unresponsive or result in unexpected process termination. 此框架不提供对这些攻击类别的缓解措施,.NET 认为 "按设计" 了此行为。The framework does not provide mitigations for these attack categories and .NET considers this behavior "by design".

.NET 已发布安全更新,可在和中缓解某些问题,例如信息泄漏或远程代码执行 DataSet.ReadXml DataTable.ReadXml.NET has released security updates to mitigate some issues such as information disclosure or remote code execution in DataSet.ReadXml and DataTable.ReadXml. .NET 安全更新可能无法提供对这些威胁类别的完整保护。The .NET security updates may not provide complete protection against these threat categories. 使用者应该评估其各个应用场景,并考虑他们遇到这些风险的可能性。Consumers should assess their individual scenarios and consider their potential exposure to these risks.

使用者应该知道,在某些情况下,这些 Api 的安全更新可能影响应用程序的兼容性。Consumers should be aware that security updates to these APIs may impact application compatibility in some situations. 此外,还可能会发现,.NET 不能几乎不能发布安全更新。Furthermore, the possibility exists that a novel vulnerability in these APIs will be discovered for which .NET can't practically publish a security update.

建议使用以下 Api 的使用者:We recommend that consumers of these APIs either:

  • 请考虑使用本文档后面所述的一种替代方法。Consider using one of the alternatives outlined later in this document.
  • 对其应用执行单独的风险评估。Perform individual risk assessments on their apps.

使用者唯一负责确定是否要使用这些 Api。It is the consumer's sole responsibility to determine whether to utilize these APIs. 消费者应评估任何安全、技术和法律风险,包括使用这些 Api 时可能附带的法规要求。Consumers should assess any security, technical, and legal risks, including regulatory requirements, that may accompany using these APIs.

通过 ASP.NET web 服务或 WCF 进行数据集和 DataTableDataSet and DataTable via ASP.NET web services or WCF

可以接受 DataSet DataTable ASP.NET (SOAP) web 服务中的或实例,如以下代码所示:It is possible to accept a DataSet or a DataTable instance in an ASP.NET (SOAP) web service, as demonstrated in the following code:

using System.Data;
using System.Web.Services;

[WebService(Namespace = "http://contoso.com/")]
public class MyService : WebService
{
    [WebMethod]
    public string MyWebMethod(DataTable dataTable)
    {
        /* Web method implementation. */
    }
}

这种情况下的变体不接受 DataSetDataTable 直接作为参数,而是将其作为整体 SOAP 序列化对象图的一部分接受,如以下代码所示:A variation on this is not to accept DataSet or DataTable directly as a parameter, but instead to accept it as part of the overall SOAP serialized object graph, as shown in the following code:

using System.Data;
using System.Web.Services;

[WebService(Namespace = "http://contoso.com/")]
public class MyService : WebService
{
    [WebMethod]
    public string MyWebMethod(MyClass data)
    {
        /* Web method implementation. */
    }
}

public class MyClass
{
    // Property of type DataTable, automatically serialized and
    // deserialized as part of the overall MyClass payload.
    public DataTable MyDataTable { get; set; }
}

或者,使用 WCF 而不是 ASP.NET web 服务:Or, using WCF instead of ASP.NET web services:

using System.Data;
using System.ServiceModel;

[ServiceContract(Namespace = "http://contoso.com/")]
public interface IMyContract
{
    [OperationContract]
    string MyMethod(DataTable dataTable);
    [OperationContract]
    string MyOtherMethod(MyClass data);
}

public class MyClass
{
    // Property of type DataTable, automatically serialized and
    // deserialized as part of the overall MyClass payload.
    public DataTable MyDataTable { get; set; }
}

在所有这些情况下,威胁模型和安全保证都与 ReadXml 和 ReadXml 节相同。In all of these cases, the threat model and security guarantees are the same as the DataSet.ReadXml and DataTable.ReadXml section.

通过 XmlSerializer 反序列化数据集或 DataTableDeserialize a DataSet or DataTable via XmlSerializer

开发人员可以使用 XmlSerializer 反序列化 DataSetDataTable 实例,如以下代码所示:Developers can use XmlSerializer to deserialize DataSet and DataTable instances, as shown in the following code:

using System.Data;
using System.IO;
using System.Xml.Serialization;

public DataSet PerformDeserialization1(Stream stream) {
    XmlSerializer serializer = new XmlSerializer(typeof(DataSet));
    return (DataSet)serializer.Deserialize(stream);
}

public MyClass PerformDeserialization2(Stream stream) {
    XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
    return (MyClass)serializer.Deserialize(stream);
}

public class MyClass
{
    // Property of type DataTable, automatically serialized and
    // deserialized as part of the overall MyClass payload.
    public DataTable MyDataTable { get; set; }
}

在这些情况下,威胁模型和安全保证与ReadXml 和 ReadXml 节相同In these cases, the threat model and security guarantees are the same as the DataSet.ReadXml and DataTable.ReadXml section

通过 JsonConvert 反序列化 DataSet 或 DataTableDeserialize a DataSet or DataTable via JsonConvert

常见的第三方 Newtonsoft.json 库 JSON.NET 可用于反序列化 DataSetDataTable 实例,如以下代码所示:The popular third-party Newtonsoft library JSON.NET can be used to deserialize DataSet and DataTable instances, as shown in the following code:

using System.Data;
using Newtonsoft.Json;

public DataSet PerformDeserialization1(string json) {
    return JsonConvert.DeserializeObject<DataSet>(data);
}

public MyClass PerformDeserialization2(string json) {
    return JsonConvert.DeserializeObject<MyClass>(data);
}

public class MyClass
{
    // Property of type DataTable, automatically serialized and
    // deserialized as part of the overall MyClass payload.
    public DataTable MyDataTable { get; set; }
}

DataSet DataTable 以这种方式从不受信任的 JSON blob 反序列化或反序列化是不安全的。Deserializing a DataSet or DataTable in this manner from an untrusted JSON blob is not safe. 此模式容易遭受拒绝服务攻击。This pattern is vulnerable to a denial of service attack. 此类攻击可能导致应用崩溃或使其无响应。Such an attack could crash the app or render it unresponsive.

备注

Microsoft 不保证或支持实现第三方库,如 Newtonsoft.JsMicrosoft does not warrant or support the implementation of third-party libraries like Newtonsoft.Json. 此信息是为完整性提供的,并且在撰写本文的时间准确无误。This information is provided for completeness and is accurate as of the time of this writing.

通过 BinaryFormatter 反序列化 DataSet 或 DataTableDeserialize a DataSet or DataTable via BinaryFormatter

开发人员决不能使用 BinaryFormatterNetDataContractSerializerSoapFormatter 或相关的 *unsafe _ 格式化 DataSet DataTable 程序从不受信任的负载反序列化或实例:Developers must never use BinaryFormatter, NetDataContractSerializer, SoapFormatter, or related *unsafe _ formatters to deserialize a DataSet or DataTable instance from an untrusted payload:

_ 这容易遭受完全远程代码执行攻击。_ This is susceptible to a full remote code execution attack.

  • 使用自定义 SerializationBinder 并不足以防止这种攻击。Using a custom SerializationBinder is not sufficient to prevent such an attack.

安全替换Safe replacements

对于以下两种应用:For apps that either:

  • 接受 DataSetDataTable 通过 .asmx SOAP 终结点或 WCF 终结点。Accept DataSet or DataTable through an .asmx SOAP endpoint or a WCF endpoint.
  • 将不受信任的数据反序列化为或的实例 DataSet DataTableDeserialize untrusted data into an instance of DataSet or DataTable.

请考虑将对象模型替换为使用 实体框架Consider replacing the object model to use Entity Framework. 实体框架:Entity Framework:

  • 是一个丰富的、面向对象的新型框架,可表示关系数据。Is a rich, modern, object-oriented framework that can represent relational data.
  • 引入 了一种不同 的数据库提供程序生态系统,使您可以轻松地通过实体框架对象模型来投影数据库查询。Brings a diverse ecosystem of database providers to make it easy to project database queries via your Entity Framework object models.
  • 在反序列化来自不受信任源的数据时提供内置保护。Offers built-in protections when deserializing data from untrusted sources.

对于使用 .aspx SOAP 终结点的应用,请考虑将这些终结点更改为使用 WCFFor apps that use .aspx SOAP endpoints, consider changing those endpoints to use WCF. WCF 是为 web 服务提供的更好的替代功能 .asmxWCF is a more fully featured replacement for .asmx web services. 可以通过 SOAP 公开WCF 终结点,以便与现有调用方兼容。WCF endpoints can be exposed via SOAP for compatibility with existing callers.

代码分析器Code analyzers

代码分析器安全规则在您的源代码编译后运行,可帮助找到与 c # 中的此安全问题和 Visual Basic 代码相关的漏洞。Code analyzer security rules, which run when your source code is compiled, can help to find vulnerabilities related to this security issue in C# and Visual Basic code. CodeAnalysis. FxCopAnalyzers 是在 nuget.org上分发的代码分析器 NuGet 包。Microsoft.CodeAnalysis.FxCopAnalyzers is a NuGet package of code analyzers that's distributed on nuget.org.

有关代码分析器的概述,请参阅 源代码分析器概述For an overview of code analyzers, see Overview of source code analyzers.

启用以下 CodeAnalysis FxCopAnalyzers 规则:Enable the following Microsoft.CodeAnalysis.FxCopAnalyzers rules:

  • CA2350:不要使用 DataTable. ReadXml ( 包含不受信任数据的 # A1CA2350: Do not use DataTable.ReadXml() with untrusted data
  • CA2351:不要使用 ReadXml ( 包含不受信任数据的 # A1CA2351: Do not use DataSet.ReadXml() with untrusted data
  • CA2352:可序列化的类型中的不安全数据集或 DataTable 可能易受到远程代码执行攻击CA2352: Unsafe DataSet or DataTable in serializable type can be vulnerable to remote code execution attacks
  • CA2353:可序列化类型中的不安全数据集或 DataTableCA2353: Unsafe DataSet or DataTable in serializable type
  • CA2354:反序列化对象图中不安全的数据集或 DataTable 可能易受到远程代码执行攻击CA2354: Unsafe DataSet or DataTable in deserialized object graph can be vulnerable to remote code execution attacks
  • CA2355:反序列化对象图中发现不安全的数据集或 DataTable 类型CA2355: Unsafe DataSet or DataTable type found in deserializable object graph
  • CA2356: web 反序列化对象图中的不安全数据集或 DataTable 类型CA2356: Unsafe DataSet or DataTable type in web deserializable object graph
  • CA2361:确保包含 DataSet 的自动生成的类。 ReadXml ( # A1 不与不受信任的数据一起使用CA2361: Ensure autogenerated class containing DataSet.ReadXml() is not used with untrusted data
  • CA2362:自动生成序列化类型中的不安全数据集或 DataTable 可能易受到远程代码执行攻击CA2362: Unsafe DataSet or DataTable in autogenerated serializable type can be vulnerable to remote code execution attacks

有关配置规则的详细信息,请参阅 使用代码分析器For more information about configuring rules, see Use code analyzers.

以下 NuGet 包中提供了新的安全规则:The new security rules are available in the following NuGet packages:

  • CodeAnalysis. FxCopAnalyzers 3.3.0: for Visual Studio 2019 版本16.3 或更高版本Microsoft.CodeAnalysis.FxCopAnalyzers 3.3.0: for Visual Studio 2019 version 16.3 or later
  • CodeAnalysis. FxCopAnalyzers 2.9.11: for Visual Studio 2017 版本15.9 或更高版本Microsoft.CodeAnalysis.FxCopAnalyzers 2.9.11: for Visual Studio 2017 version 15.9 or later