数据集和 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
SqlSingle
和SqlString
。Primitives 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
, andSqlString
. - 常用的非基元:
Type
、Uri
和BigInteger
。Commonly used non-primitives:Type
,Uri
, andBigInteger
. - 常用的 系统 类型:
Color
、Point
、PointF
、、、Rectangle
RectangleF
Size
和SizeF
。Commonly used System.Drawing types:Color
,Point
,PointF
,Rectangle
,RectangleF
,Size
, andSizeF
. 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 加载到现有的 DataSet
或 DataTable
实例时,也会考虑现有的列定义。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.
备注
向添加列后 DataTable
, ReadXml
将不会从 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
DataTable
。The object type restrictions also apply when using XmlSerializer
to deserialize an instance of DataSet
or DataTable
. 但是,当使用 BinaryFormatter
反序列化或的实例时,它们可能不适用 DataSet
DataTable
。However, 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.CustomType
。The 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.SetData
。On .NET Framework, the list of allowed types may be extended both with App.config and AppDomain.SetData
. 在这种情况下, DataSet
和 DataTable
将允许将对象作为数据的一部分进行反序列化(如果其类型存在于任一列表中)。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 中, DataSet
并 DataTable
提供审核模式功能。In .NET Framework, DataSet
and DataTable
provide an audit mode capability. 当启用审核模式时, DataSet
并 DataTable
根据允许的类型列表比较传入对象的类型。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. 相反, DataSet
并 DataTable
通知任何附加的 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
限制 DataTable
:If 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. 使用此机制时,请确保应用 不 使用 DataSet
或 DataTable
读取不受信任的输入。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
DataTable
。The 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\AppContext
。The 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
尽管 DataSet
和 DataTable
确实对允许在反序列化 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. 下面是 DataSet
或 DataTable
实例可能读取不受信任的输入的一系列非详尽列表。The following is a non-exhaustive list of ways that a DataSet
or DataTable
instance might read untrusted input.
DataAdapter
引用数据库,DataAdapter.Fill
方法用于使用DataSet
数据库查询的内容来填充。ADataAdapter
references a database, and theDataAdapter.Fill
method is used to populate aDataSet
with the contents of a database query.DataSet.ReadXml
或DataTable.ReadXml
方法用于读取包含列和行信息的 XML 文件。TheDataSet.ReadXml
orDataTable.ReadXml
method is used to read an XML file containing column and row information.DataSet
或DataTable
实例序列化为 ASP.NET (SOAP) web 服务或 WCF 终结点。ADataSet
orDataTable
instance is serialized as part of a ASP.NET (SOAP) web services or WCF endpoint.- 序列化程序(如)
XmlSerializer
用于DataSet
从 XML 流反序列化或DataTable
实例。A serializer such asXmlSerializer
is used to deserialize aDataSet
orDataTable
instance from an XML stream. - 序列化程序(如)
JsonConvert
用于DataSet
从 JSON 流反序列化或DataTable
实例。A serializer such asJsonConvert
is used to deserialize aDataSet
orDataTable
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 asBinaryFormatter
is used to deserialize aDataSet
orDataTable
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. */
}
}
这种情况下的变体不接受 DataSet
或 DataTable
直接作为参数,而是将其作为整体 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
反序列化 DataSet
和 DataTable
实例,如以下代码所示: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 可用于反序列化 DataSet
和 DataTable
实例,如以下代码所示: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.Js。Microsoft 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
开发人员决不能使用 BinaryFormatter
、 NetDataContractSerializer
、 SoapFormatter
或相关的 *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 customSerializationBinder
is not sufficient to prevent such an attack.
安全替换Safe replacements
对于以下两种应用:For apps that either:
- 接受
DataSet
或DataTable
通过 .asmx SOAP 终结点或 WCF 终结点。AcceptDataSet
orDataTable
through an .asmx SOAP endpoint or a WCF endpoint. - 将不受信任的数据反序列化为或的实例
DataSet
DataTable
。Deserialize untrusted data into an instance ofDataSet
orDataTable
.
请考虑将对象模型替换为使用 实体框架。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 终结点的应用,请考虑将这些终结点更改为使用 WCF。For apps that use .aspx
SOAP endpoints, consider changing those endpoints to use WCF. WCF 是为 web 服务提供的更好的替代功能 .asmx
。WCF 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