Compartir a través de


Guía de seguridad de DataSet y DataTable

Este artículo se aplica a:

  • .NET Framework (todas las versiones)
  • .NET Core y versiones posteriores
  • .NET 5 y versiones posteriores

Los tipos DataSet y DataTable son componentes heredados de .NET que permiten representar conjuntos de datos como objetos administrados. Estos componentes se introdujeron en .NET Framework 1.0 como parte de la infraestructura de ADO.NET original. Su objetivo era proporcionar una vista administrada sobre un conjunto de datos relacional para abstraer si el origen subyacente de los datos era XML, SQL u otra tecnología.

Para obtener más información sobre ADO.NET, incluidos paradigmas de vista de datos de tipo más moderno, consulte la documentación de ADO.NET.

Restricciones predeterminadas al deserializar un objeto DataSet o DataTable de XML

En todas las versiones compatibles de .NET Framework, .NET Core y .NET, DataSet y DataTable establecen las restricciones siguientes sobre los tipos de objetos que pueden estar presentes en los datos deserializados. De forma predeterminada, esta lista se restringe a:

  • Elementos primitivos y equivalentes primitivos: 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 y SqlString.
  • Elementos no primitivos de uso habitual: Type, Uri y BigInteger.
  • Tipos System.Drawing de uso habitual: Color, Point, PointF, Rectangle, RectangleF, Size y SizeF.
  • Tipos Enum.
  • Matrices y listas de los tipos anteriores

Si los datos XML entrantes contienen un objeto cuyo tipo no está en esta lista:

  • Se produce una excepción con el mensaje y el seguimiento de la pila siguientes. Mensaje de error: System.InvalidOperationException : El tipo "<Nombre de tipo>, Version=<n.n.n.n>, Culture=<referencia cultural>, PublicKeyToken=<valor de token>" no se permite aquí. Seguimiento de la pila: en System.Data.TypeLimiter.EnsureTypeIsAllowed(Type type, TypeLimiter capturedLimiter) en System.Data.DataColumn.UpdateColumnType(Type type, StorageType typeCode) en System.Data.DataColumn.set_DataType(Type value)

  • Se produce un error en la operación de deserialización.

Al cargar XML en una instancia de DataSet o DataTable existente, también se tienen en cuenta las definiciones de columna existentes. Si la tabla ya contiene una definición de columna de un tipo personalizado, ese tipo se agrega temporalmente a la lista de permitidos durante la operación de deserialización de XML.

Nota

Una vez que agregue columnas a un objeto DataTable, ReadXml no leerá el esquema del XML y, si el esquema no coincide, tampoco lo leerá en los registros, por lo que tendrá que agregar todas las columnas usted mismo para usar este método.

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

Las restricciones de tipo de objeto también se aplican cuando se usa XmlSerializer para deserializar una instancia de DataSet o DataTable. Sin embargo, puede que no se apliquen al usar BinaryFormatter para deserializar una instancia de DataSet o DataTable.

Las restricciones de tipo de objeto no se aplican al usar DataAdapter.Fill, como cuando una instancia de DataTable se rellena directamente desde una base de datos sin usar las API de deserialización XML.

Ampliación de la lista de tipos permitidos

Una aplicación puede ampliar la lista de tipos permitidos para incluir tipos personalizados, además de los tipos integrados enumerados anteriormente. Si amplía la lista de tipos permitidos, el cambio afecta a todas las instancias de DataSet y DataTable dentro de la aplicación. Los tipos no se pueden quitar de la lista de tipos permitidos integrada.

Extensión a través de la configuración (.NET Framework 4.0 y versiones posteriores)

App.config se puede usar para ampliar la lista de tipos permitidos. Para ampliar la lista de tipos permitidos:

  • Use el elemento <configSections> para agregar una referencia a la sección de configuración de System.Data.
  • Use <system.data.dataset.serialization>/<allowedTypes> para especificar tipos adicionales.

Cada elemento <add> debe especificar solo un tipo mediante su nombre de tipo calificado con el ensamblado. Para agregar tipos adicionales a la lista de tipos permitidos, use varios elementos <add>.

En el ejemplo siguiente se muestra cómo ampliar la lista de tipos permitidos mediante la adición del tipo personalizado 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>

Para recuperar el nombre completo de ensamblado de un tipo, use la propiedad Type.AssemblyQualifiedName, tal y como se muestra en el código siguiente.

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

Ampliación a través de la configuración (.NET Framework 2.0 - 3.5)

Si la aplicación tiene como destino .NET Framework 2.0 o 3.5, también puede usar el mecanismo anterior con App.config para ampliar la lista de tipos permitidos. Sin embargo, el elemento <configSections> tendrá un aspecto ligeramente distinto, como se muestra en el código siguiente:

<?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>

Ampliación mediante programación (.NET Framework, .NET Core, .NET 5 y versiones posteriores)

La lista de tipos permitidos también se puede ampliar mediante programación con AppDomain.SetData y la clave conocida System.Data.DataSetDefaultAllowedTypes, tal y como se muestra en el código siguiente.

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

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

Si usa el mecanismo de extensión, el valor asociado a la clave System.Data.DataSetDefaultAllowedTypes debe ser de tipo Type[].

En .NET Framework, la lista de tipos permitidos se puede ampliar tanto con App.config como con AppDomain.SetData. En este caso, DataSet y DataTable permitirán que un objeto se deserialice como parte de los datos si su tipo está presente en cualquiera de las listas.

Ejecución de una aplicación en modo auditoría (.NET Framework)

En .NET Framework, DataSet y DataTable proporcionan la funcionalidad de modo auditoría. Cuando el modo auditoría está habilitado, DataSet y DataTable comparan los tipos de objetos entrantes con la lista de tipos permitidos. Sin embargo, si se encuentra un objeto cuyo tipo no está permitido, no se produce una excepción. En su lugar, DataSet y DataTable notifican a cualquier instancia de TraceListener asociada que hay un tipo sospechoso, lo que permite a TraceListener registrar esta información. No se produce ninguna excepción y la operación de deserialización continúa.

Advertencia

La ejecución de una aplicación en "modo auditoría" debe ser únicamente una medida temporal empleada para las pruebas. Cuando el modo auditoría está habilitado, DataSet y DataTable no aplican restricciones de tipo, lo que puede introducir una vulnerabilidad de seguridad en de la aplicación. Para obtener más información, consulte las secciones tituladas Eliminación de todas las restricciones de tipos y Seguridad respecto a entradas que no son de confianza.

El modo auditoría se puede habilitar a través de App.config:

  • Consulte la sección Ampliación a través de la configuración de este documento para obtener información sobre el valor adecuado que se debe asignar al elemento <configSections>.
  • Use <allowedTypes auditOnly="true"> para habilitar el modo auditoría, tal y como se muestra en el marcado siguiente.
<?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>

Una vez habilitado el modo auditoría, puede usar App.config para conectar su TraceListener preferido con el objeto DataSet integrado en TraceSource.. El nombre del origen de seguimiento integrado es System.Data.DataSet. En el ejemplo siguiente se muestra cómo escribir eventos de seguimiento en la consola y en un archivo de registro del disco.

<?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>

Para obtener más información sobre TraceSource y TraceListener, consulte el documento Procedimiento para usar TraceSource y filtros con agentes de escucha de seguimiento.

Nota

La ejecución de una aplicación en modo auditoría no está disponible en .NET Core ni en .NET 5 y versiones posteriores.

Eliminación de todas las restricciones de tipo

Si una aplicación debe quitar todas las restricciones de limitación de tipos de DataSet y DataTable:

  • Hay varias opciones para suprimir las restricciones de limitación de tipos.
  • Las opciones disponibles dependen del marco al que esté destinada la aplicación.

Advertencia

La eliminación de todas las restricciones de tipo puede introducir una vulnerabilidad de seguridad en la aplicación. Al usar este mecanismo, asegúrese de que la aplicación no use DataSet ni DataTable para leer entradas que no son de confianza. Para obtener más información, consulte CVE-2020-1147 y la sección siguiente titulada Seguridad respecto a entradas que no son de confianza.

Mediante la configuración de AppContext (.NET Framework 4.6 y versiones posteriores, .NET Core 2.1 y versiones posteriores, .NET 5 y versiones posteriores)

El modificador de AppContext, Switch.System.Data.AllowArbitraryDataSetTypeInstantiation, cuando se establece en true, quita todas las restricciones de limitación de tipos de DataSet y DataTable.

En .NET Framework, este modificador puede habilitarse a través de App.config, como se muestra en la configuración siguiente:

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

En ASP.NET, el elemento <AppContextSwitchOverrides> no está disponible. En su lugar, el modificador puede habilitarse a través de Web.config, como se muestra en la configuración siguiente:

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

Para obtener más información, consulte el elemento <AppContextSwitchOverrides>.

En .NET Core, .NET 5 y ASP.NET Core, esta configuración se controla mediante runtimeconfig.json, como se muestra en el JSON siguiente:

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

Para obtener más información, consulte "Opciones de configuración del entorno de ejecución de .NET Core".

AllowArbitraryDataSetTypeInstantiation también puede establecerse mediante programación a través de AppContext.SetSwitch, en lugar de usar un archivo de configuración, como se muestra en el código siguiente:

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

Si elige el enfoque de programación anterior, la llamada a AppContext.SetSwitch debe producirse de forma temprana al iniciar las aplicaciones.

A través del registro de todo el equipo (.NET Framework 2.0 - 4.x)

Si AppContext no está disponible, las comprobaciones de limitación de tipos se pueden deshabilitar con el registro de Windows:

  • Un administrador debe configurar el registro.
  • El uso del registro es un cambio en toda la máquina y afectará a todas las aplicaciones que se ejecutan en la máquina.
Tipo Valor
Clave del Registro HKLM\SOFTWARE\Microsoft\.NETFramework\AppContext
Nombre del valor Switch.System.Data.AllowArbitraryDataSetTypeInstantiation
Tipo de valor REG_SZ
Datos del valor true

En un sistema operativo de 64 bits, es necesario agregar este valor para la clave de 64 bits (mostrada anteriormente) y la clave de 32 bits. La clave de 32 bits se encuentra en HKLM\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\AppContext.

Para obtener más información sobre el uso del registro para configurar AppContext, consulte "AppContext para consumidores de bibliotecas".

Seguridad respecto a entradas que no son de confianza

Aunque DataSet y DataTable imponen limitaciones predeterminadas a los tipos que pueden estar presentes durante la deserialización de cargas XML, DataSet y DataTable, en general, no son seguros cuando se rellenan con entradas que no son de confianza. A continuación, se muestra una lista no exhaustiva de formas en las que una instancia de DataSet o DataTable puede leer entradas que no son de confianza.

  • Un objeto DataAdapter hace referencia a una base de datos y el método DataAdapter.Fill se usa para rellenar un DataSet con el contenido de una consulta de base de datos.
  • Se usa el método DataSet.ReadXml o DataTable.ReadXml para leer un archivo XML que contiene información de columnas y de filas.
  • Se serializa una instancia de DataSet o DataTable como parte de un servicio web de ASP.NET (SOAP) o un punto de conexión WCF.
  • Se usa un serializador como XmlSerializer para deserializar una instancia de DataSet o DataTable de una secuencia XML.
  • Se usa un serializador como JsonConvert para deserializar una instancia de DataSet o DataTable de una secuencia JSON. JsonConvert es un método de la conocida biblioteca de terceros Newtonsoft.Json.
  • Se usa un serializador como BinaryFormatter para deserializar una instancia de DataSet o DataTable de una secuencia de bytes sin formato.

En este documento se describen las consideraciones de seguridad para los escenarios anteriores.

Uso de DataAdapter.Fill para rellenar un objeto DataSet de un origen de datos que no es de confianza

Una instancia de DataSet se puede rellenar desde un objeto DataAdapter mediante el método DataAdapter.Fill, como se muestra en el ejemplo siguiente.

// 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");

(El ejemplo de código anterior forma parte de un ejemplo más grande que se encuentra en Rellenar un conjunto de datos desde un objeto DataAdapter).

La mayoría de las aplicaciones pueden simplificarse y asumir que su capa de base de datos es de confianza. Sin embargo, si tiene el hábito de realizar el modelado de amenazas de las aplicaciones, su modelo de amenazas puede considerar que hay un límite de confianza entre la aplicación (cliente) y la capa de base de datos (servidor). El uso de la autenticación mutua o de la autenticación de AAD entre el cliente y el servidor es una forma de ayudar a abordar los riesgos asociados a esto. En el resto de esta sección se describe el posible resultado de que un cliente se conecte a un servidor que no es de confianza.

Las consecuencias de apuntar un objeto DataAdapter a un origen de datos que no es de confianza dependen de la implementación del propio DataAdapter.

SqlDataAdapter

En el caso del tipo SqlDataAdapter integrado, hacer referencia a un origen de datos que no es de confianza puede dar lugar a un ataque por denegación de servicio (DoS). El ataque DoS puede provocar que la aplicación deje de responder o se bloquee. Si un atacante puede infiltrar un archivo DLL junto con la aplicación, también puede lograr la ejecución de código local.

Otros tipos de DataAdapter

Las implementaciones de DataAdapter de terceros deben realizar sus propias evaluaciones sobre las garantías de seguridad que proporcionan frente a las entradas que no son de confianza. .NET no puede ofrecer ninguna garantía de seguridad con respecto a estas implementaciones.

DataSet.ReadXml y DataTable.ReadXml

Los métodos DataSet.ReadXml y DataTable.ReadXml no son seguros cuando se usan con entradas que no son de confianza. Se recomienda encarecidamente que los consumidores consideren el uso de una de las alternativas que se describen más adelante en este documento.

Las implementaciones de DataSet.ReadXml y DataTable.ReadXml se crearon originalmente antes de que las vulnerabilidades de serialización fueran una categoría de amenaza bien entendida. Como resultado, el código no sigue los procedimientos recomendados de seguridad actuales. Estas API se pueden usar como vectores para que los atacantes realicen ataques DoS contra aplicaciones web. Es posible que estos ataques hagan que el servicio web deje de responder o que se produzca una terminación inesperada del proceso. El marco no proporciona mitigaciones para estas categorías de ataque y .NET considera este comportamiento "por diseño".

.NET ha publicado actualizaciones de seguridad para mitigar algunos problemas, como la divulgación de información o la ejecución remota de código en DataSet.ReadXml y DataTable.ReadXml. Es posible que las actualizaciones de seguridad de .NET no proporcionen protección completa frente a estas categorías de amenazas. Los consumidores deben evaluar sus escenarios individuales y considerar su posible exposición a estos riesgos.

Los consumidores deben tener en cuenta que las actualizaciones de seguridad de estas API pueden afectar a la compatibilidad de aplicaciones en algunas situaciones. Además, existe la posibilidad de que se detecte una vulnerabilidad nueva en estas API para la que .NET no pueda publicar de forma práctica una actualización de seguridad.

Se recomienda que los consumidores de estas API:

  • Consideren la posibilidad de usar una de las alternativas descritas más adelante en este documento.
  • Realicen valoraciones de riesgo individuales en sus aplicaciones.

Es responsabilidad exclusiva del consumidor determinar si se usan estas API. Los consumidores deben evaluar cualquier riesgo de seguridad, técnico y legal que pueda conllevar el uso de estas API, incluidos los requisitos normativos.

DataSet y DataTable a través de servicios web ASP.NET o WCF

Es posible aceptar una instancia de DataSet o DataTable en un servicio web de ASP.NET (SOAP), como se muestra en el código siguiente:

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. */
    }
}

Una variación de este proceso es no aceptar DataSet ni DataTable directamente como parámetro, sino aceptarlo como parte del gráfico global de objetos serializados SOAP, como se muestra en el código siguiente:

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; }
}

Otra opción es usar WCF en lugar de servicios web de ASP.NET:

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; }
}

En todos estos casos, las garantías de seguridad y el modelo de amenazas son los mismos que en la sección DataSet.ReadXml y DataTable.ReadXml.

Deserialización de un DataSet o DataTable a través de XmlSerializer

Los desarrolladores pueden usar XmlSerializer para deserializar las instancias de DataSet y DataTable, como se muestra en el código siguiente:

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; }
}

En estos casos, las garantías de seguridad y el modelo de amenazas son los mismos que en la sección DataSet.ReadXml y DataTable.ReadXml.

Deserialización de un DataSet o DataTable a través de JsonConvert

La popular biblioteca de terceros de Newtonsoft Json.NET se puede usar para deserializar las instancias de DataSet y DataTable, como se muestra en el código siguiente:

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; }
}

La deserialización de esta forma de un objeto DataSet o DataTable de un blob JSON que no es de confianza no es segura. Este patrón es vulnerable a un ataque por denegación de servicio. Este ataque puede bloquear la aplicación o hacer que deje de responder.

Nota

Microsoft no garantiza ni admite la implementación de bibliotecas de terceros como Newtonsoft.Json. Esta información se proporciona con fines de exhaustividad y es precisa en el momento de redactar este documento.

Deserialización de un DataSet o DataTable a través de BinaryFormatter

Nunca debe usar BinaryFormatter, NetDataContractSerializer, SoapFormatter ni otros formateadores no seguros relacionados para deserializar una instancia de DataSet o DataTable de una carga que no sea de confianza:

  • Esto es susceptible a un ataque de ejecución remota de código completo.
  • El uso de un objeto SerializationBinder personalizado no es suficiente para evitar este tipo de ataque.

Reemplazos seguros

Para las aplicaciones que:

  • Aceptan DataSet o DataTable a través de un punto de conexión SOAP .asmx o un punto de conexión WCF.
  • Deserializan datos que no son de confianza en una instancia de DataSet o DataTable.

Considere la posibilidad de reemplazar el modelo de objetos para usar Entity Framework. Entity Framework:

  • Es un marco enriquecido, moderno y orientado a objetos que puede representar datos relacionales.
  • Aporta un ecosistema diverso de proveedores de bases de datos para facilitar la proyección de consultas de base de datos a través de los modelos de objetos de Entity Framework.
  • Ofrece protección integrada al deserializar los datos de orígenes que no son de confianza.

En el caso de las aplicaciones que usan puntos de conexión SOAP .aspx, considere la posibilidad de cambiar esos puntos de conexión para usar WCF. WCF es un sustituto con todas las características para los servicios web de .asmx. Los puntos de conexión de WCF se pueden exponer a través de SOAP para la compatibilidad con los autores de llamada existentes.

Analizadores de código

Las reglas de seguridad del analizador de código, que se ejecutan cuando se compila el código fuente, pueden ayudar a encontrar vulnerabilidades relacionadas con este problema de seguridad en el código de C# y Visual Basic. Microsoft.CodeAnalysis.FxCopAnalyzers es un paquete NuGet de analizadores de código que se distribuye en nuget.org.

Para obtener información general sobre los analizadores de código, consulte Información general sobre el análisis de código fuente.

Habilite las reglas Microsoft.CodeAnalysis.FxCopAnalyzers siguientes:

  • CA2350: No usar DataTable.ReadXml() con datos que no son de confianza
  • CA2351: No usar DataSet.ReadXml() con datos que no son de confianza
  • CA2352: Un objeto DataSet o DataTable no seguro en un tipo serializable puede ser vulnerable a ataques de ejecución remota de código
  • CA2353: Objeto DataSet o DataTable no seguro en un tipo serializable
  • CA2354: Un objeto DataSet o DataTable no seguro en un gráfico de objetos deserializado puede ser vulnerable a ataques de ejecución remota de código
  • CA2355: Se encontró un tipo DataSet o DataTable no seguro en el gráfico de objetos deserializables
  • CA2356: Tipo DataSet o DataTable no seguro en el gráfico de objetos deserializables web
  • CA2361: Asegurarse de que la clase autogenerada que contiene DataSet.ReadXml() no se utilice con datos que no son de confianza
  • CA2362: Un elemento DataSet o DataTable no seguro en un tipo serializable autogenerado puede ser vulnerable a ataques de ejecución remota de código

Para obtener más información sobre cómo configurar reglas, consulte Uso de analizadores de código.

Las nuevas reglas de seguridad están disponibles en los paquetes NuGet siguientes:

  • Microsoft.CodeAnalysis.FxCopAnalyzers 3.3.0: para Visual Studio 2019 versión 16.3 o posterior
  • Microsoft.CodeAnalysis.FxCopAnalyzers 2.9.11: para Visual Studio 2017 versión 15.9 o posterior