Condividi tramite


Linee guida per la sicurezza di DataSet e DataTable

Questo articolo si applica a:

  • .NET Framework (tutte le versioni)
  • .NET Core e versioni successive
  • .NET 5 e versioni successive

I tipi DataSet e DataTable sono componenti .NET legacy che consentono di rappresentare i set di dati come oggetti gestiti. Questi componenti sono stati introdotti in .NET Framework 1.0 come parte dell'infrastruttura di ADO.NET originale. L'obiettivo era quello di fornire una vista gestita su un set di dati relazionale, a prescindere dal fatto che l'origine sottostante dei dati fosse XML, SQL o un'altra tecnologia.

Per altre informazioni su ADO.NET, tra cui paradigmi più moderni di visualizzazione dei dati, vedere la documentazione di ADO.NET.

Restrizioni predefinite quando si deserializza un oggetto DataSet o DataTable da XML

In tutte le versioni supportate di .NET Framework, .NET Core e .NET DataSet e DataTable applicano le restrizioni seguenti sui tipi di oggetti che possono essere presenti nei dati deserializzati. Per impostazione predefinita, questo elenco è limitato a:

  • Primitive ed equivalenti di primitive: 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 e SqlString.
  • Non primitive comunemente usate: Type, Uri e BigInteger.
  • Tipi System.Drawing comunemente usati: Color, Point, PointF, Rectangle, RectangleF, Size e SizeF.
  • Tipi Enum.
  • Matrici ed elenchi dei tipi precedenti.

Se i dati XML in ingresso contengono un oggetto il cui tipo non è incluso nell'elenco:

  • Viene generata un'eccezione con il messaggio e l'analisi dello stack seguenti. Messaggio di errore: System.InvalidOperationException: Tipo '<nome tipo>, Version=<n.n.n.n>, Culture=<impostazioni cultura>, PublicKeyToken=<valore token>' non consentito in questo punto. Analisi dello stack: in System.Data.TypeLimiter.EnsureTypeIsAllowed(Type type, TypeLimiter capturedLimiter) in System.Data.DataColumn.UpdateColumnType(Type type, StorageType typeCode) in System.Data.DataColumn.set_DataType(Type value)

  • L'operazione di deserializzazione non riesce.

Quando si carica codice XML in un'istanza di DataSet o DataTable esistente, vengono prese in considerazione anche le definizioni di colonna esistenti. Se la tabella contiene già una definizione di colonna di un tipo personalizzato, tale tipo viene temporaneamente aggiunto all'elenco di elementi consenti per la durata dell'operazione di deserializzazione XML.

Nota

Dopo aver aggiunto le colonne a un oggetto DataTable, ReadXml non leggerà lo schema dal codice XML e, se lo schema non corrisponde, non leggerà nemmeno i record, quindi sarà necessario aggiungere tutte le colonne manualmente per usare questo metodo.

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

Le restrizioni relative al tipo di oggetto si applicano anche quando si usa XmlSerializer per deserializzare un'istanza di DataSet o DataTable. Tuttavia, potrebbero non essere applicabili quando si usa BinaryFormatter per deserializzare un'istanza di DataSet o DataTable.

Le restrizioni relative al tipo di oggetto non si applicano quando si usa DataAdapter.Fill, ad esempio quando un'istanza di DataTable viene popolata direttamente da un database senza usare le API di deserializzazione XML.

Estendere l'elenco dei tipi consentiti

Un'app può estendere l'elenco dei tipi consentiti per includere tipi personalizzati oltre ai tipi predefiniti elencati in precedenza. Se si estende l'elenco dei tipi consentiti, la modifica influisce su tutte le istanze di DataSet e DataTable all'interno dell'app. I tipi non possono essere rimossi dall'elenco dei tipi consentiti predefiniti.

Estendere tramite la configurazione (.NET Framework 4.0 e versioni successive)

App.config può essere usato per estendere l'elenco dei tipi consentiti. Per estendere l'elenco dei tipi consentiti:

  • Usare l'elemento <configSections> per aggiungere un riferimento alla sezione della configurazione System.Data.
  • Usare <system.data.dataset.serialization>/<allowedTypes> per specificare tipi aggiuntivi.

Ogni elemento <add> deve specificare un solo tipo usando il nome completo dell'assembly di un tipo. Per aggiungere altri tipi all'elenco dei tipi consentiti, usare più elementi <add>.

L'esempio seguente illustra l'estensione dell'elenco dei tipi consentiti aggiungendo il tipo Fabrikam.CustomTypepersonalizzato.

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

Per recuperare il nome completo dell'assembly di un tipo, usare la proprietà Type.AssemblyQualifiedName, come illustrato nel codice seguente.

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

Estendere tramite la configurazione (.NET Framework 2.0 - 3.5)

Se l'app è destinata a .NET Framework 2.0 o 3.5, è comunque possibile usare il meccanismo App.config precedente per estendere l'elenco dei tipi consentiti. Tuttavia, l'elemento <configSections> avrà un aspetto leggermente diverso, come illustrato nel codice seguente:

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

Estendere a livello di codice (.NET Framework, .NET Core, .NET 5+)

L'elenco dei tipi consentiti può anche essere esteso a livello di codice usando AppDomain.SetData con la chiave nota System.Data.DataSetDefaultAllowedTypes, come illustrato nel codice seguente.

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

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

Se si usa il meccanismo di estensione, il valore associato alla chiave System.Data.DataSetDefaultAllowedTypes deve essere di tipo Type[].

In .NET Framework l'elenco dei tipi consentiti può essere esteso sia con App.config che con AppDomain.SetData. In questo caso, DataSet e DataTable consentiranno la deserializzazione di un oggetto come parte dei dati se il relativo tipo è presente in uno degli elenchi.

Eseguire un'app in modalità di controllo (.NET Framework)

In .NET Framework DataSet e DataTable forniscono una funzionalità di modalità di controllo. Quando la modalità di controllo è abilitata DataSet e DataTable confrontano i tipi di oggetti in ingresso con l'elenco dei tipi consentiti. Tuttavia, se viene visualizzato un oggetto il cui tipo non è consentito, non viene generata un'eccezione. Invece, DataSet e DataTable notificano a tutte le istanze di TraceListener associate che è presente un tipo sospetto, consentendo a TraceListener di registrare queste informazioni. Non viene generata alcuna eccezione e l'operazione di deserializzazione continua.

Avviso

L'esecuzione di un'app in "modalità di controllo" deve essere solo una misura temporanea usata per i test. Quando la modalità di controllo è abilitata, DataSet e DataTable non impongono restrizioni sui tipi, che possono introdurre un problema di sicurezza all'interno dell'app. Per altre informazioni, vedere le sezioni intitolate Rimozione di tutte le restrizioni sui tipi e Sicurezza rispetto all'input non attendibile.

La modalità di controllo può essere abilitata tramite App.config:

  • Vedere la sezione Estensione tramite la configurazione di questo documento per informazioni sul valore corretto da inserire per l'elemento <configSections>.
  • Usare <allowedTypes auditOnly="true"> per abilitare la modalità di controllo, come illustrato nel markup seguente.
<?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>

Dopo aver abilitato la modalità di controllo, è possibile usare App.config per connettere l'oggetto TraceListener preferito a DataSet, l'oggetto predefinito TraceSource. Il nome dell'origine della traccia predefinita è System.Data.DataSet. L'esempio seguente illustra la scrittura di eventi di traccia nella console e in un file di log su 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>

Per altre informazioni su TraceSource e TraceListener, vedere il documento Procedura: Usare TraceSource e filtri con listener di traccia.

Nota

L'esecuzione di un'app in modalità di controllo non è disponibile in .NET Core o in .NET 5 e versioni successive.

Rimuovere tutte le restrizioni sui tipi

Se un'app deve rimuovere tutte le restrizioni relative alla limitazione dei tipi da DataSet e DataTable:

  • Sono disponibili diverse opzioni per eliminare le restrizioni relative alla limitazione dei tipi.
  • Le opzioni disponibili dipendono dal framework di destinazione dell'app.

Avviso

La rimozione di tutte le restrizioni sui tipi può introdurre un problema di sicurezza all'interno dell'app. Quando si usa questo meccanismo, assicurarsi che l'app non usi DataSet o DataTable per leggere input non attendibile. Per altre informazioni, vedere CVE-2020-1147 e la sezione seguente intitolata Sicurezza rispetto all'input non attendibile.

Tramite la configurazione di AppContext (.NET Framework 4.6 e versioni successive, .NET Core 2.1 e versioni successive, .NET 5 e versioni successive)

L'opzione di AppContext, Switch.System.Data.AllowArbitraryDataSetTypeInstantiation, se impostata su true, rimuove tutte le restrizioni relative alla limitazione dei tipi da DataSet e DataTable.

In .NET Framework questa opzione può essere abilitata tramite App.config, come illustrato nella configurazione seguente:

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

In ASP.NET l'elemento <AppContextSwitchOverrides> non è disponibile. Invece, l'opzione può essere abilitata tramite Web.config, come illustrato nella configurazione seguente:

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

Per altre informazioni, vedere l'elemento <AppContextSwitchOverrides>.

In .NET Core, .NET 5 e ASP.NET Core questa impostazione è controllata da runtimeconfig.json, come illustrato nel codice JSON seguente:

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

Per altre informazioni, vedere "Impostazioni di configurazione del runtime .NET Core".

È anche possibile impostare AllowArbitraryDataSetTypeInstantiation a livello di codice tramite AppContext.SetSwitch invece di usare un file di configurazione, come illustrato nel codice seguente:

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

Se si sceglie l'approccio programmatico precedente, la chiamata a AppContext.SetSwitch deve essere eseguita all'inizio dell'avvio delle app.

Tramite il Registro di sistema a livello di computer (.NET Framework 2.0 - 4.x)

Se AppContext non è disponibile, i controlli di limitazione dei tipi possono essere disabilitati con il Registro di sistema di Windows:

  • Un amministratore deve configurare il Registro di sistema.
  • L'uso del Registro di sistema è una modifica a livello di computer e influirà su tutte le app in esecuzione nel computer.
Type Valore
Chiave del Registro di sistema HKLM\SOFTWARE\Microsoft\.NETFramework\AppContext
Nome valore Switch.System.Data.AllowArbitraryDataSetTypeInstantiation
Tipo di valore REG_SZ
Dati valore true

In un sistema operativo a 64 bit, questo valore deve essere aggiunto sia per la chiave a 64 bit (illustrata in precedenza) che per la chiave a 32 bit. La chiave a 32 bit si trova in HKLM\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\AppContext.

Per altre informazioni sull'uso del Registro di sistema per configurare AppContext, vedere "AppContext per i consumer di librerie".

Sicurezza rispetto all'input non attendibile

Anche se DataSet e DataTable impongono limitazioni predefinite sui tipi che possono essere presenti durante la deserializzazione dei payload XML, DataSet e DataTable sono in genere non sicuri quando vengono popolati con input non attendibile. Di seguito è riportato un elenco non completo dei modi in cui un'istanza di DataSet o DataTable potrebbe leggere input non attendibile.

  • Un oggetto DataAdapter fa riferimento a un database e il metodo DataAdapter.Fill viene utilizzato per popolare un oggetto DataSet con il contenuto di una query di database.
  • Il metodo DataSet.ReadXml o DataTable.ReadXml viene usato per leggere un file XML contenente informazioni sulle colonne e sulle righe.
  • Un'istanza di DataSet o DataTable viene serializzata come parte di un endpoint WCF o dei servizi Web ASP.NET (SOAP).
  • Un serializzatore, ad esempio XmlSerializer, viene usato per deserializzare un'istanza di DataSet o DataTable da un flusso XML.
  • Un serializzatore, ad esempio JsonConvert, viene usato per deserializzare un'istanza di DataSet o DataTable da un flusso JSON. JsonConvert è un metodo della popolare libreria Newtonsoft.Json di terze parti.
  • Un serializzatore, ad esempio BinaryFormatter, viene usato per deserializzare un'istanza di DataSet o DataTable da un flusso di byte non elaborato.

Questo documento illustra le considerazioni sulla sicurezza per gli scenari precedenti.

Usare DataAdapter.Fill per popolare un oggetto DataSet da un'origine dati non attendibile

Un'istanza di DataSet può essere popolata da un oggetto DataAdapter usando il metodo DataAdapter.Fill, come illustrato nell'esempio seguente.

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

L'esempio di codice precedente fa parte di un esempio più ampio disponibile in Popolamento di un set di dati da un oggetto DataAdapter.

La maggior parte delle app può semplificare e presupporre che il livello di database sia attendibile. Tuttavia, se si ha l'abitudine di modellare le app in base alle minacce, il modello di minaccia può considerare che esista un margine di attendibilità tra l'applicazione (client) e il livello del database (server). L'uso dell'autenticazione reciproca o dell'autenticazione AAD tra client e server è un modo per risolvere i rischi associati. Nella parte restante di questa sezione viene illustrato il possibile risultato di una connessione client a un server non attendibile.

Se un oggetto DataAdapter punta a un'origine dati non attendibile, le conseguenze dipendono dall'implementazione dell'oggetto DataAdapter stesso.

SqlDataAdapter

Per il tipo predefinito SqlDataAdapter, fare riferimento a un'origine dati non attendibile potrebbe causare un attacco Denial of Service (DoS). L'attacco DoS potrebbe causare la mancata risposta o l'arresto anomalo dell'app. Se un utente malintenzionato riesce a installare una DLL insieme all'app, potrebbe anche essere in grado di ottenere l'esecuzione di codice locale.

Altri tipi di DataAdapter

Le implementazioni di DataAdapter di terze parti devono valutare autonomamente le garanzie di sicurezza che offrono di fronte a input non attendibili. NET non può fornire alcuna garanzia di sicurezza per queste implementazioni.

DataSet.ReadXml e DataTable.ReadXml

I metodi DataSet.ReadXml e DataTable.ReadXml non sono sicuri quando vengono usati con input non attendibile. Si consiglia agli utenti di valutare invece l'opportunità di usare una delle alternative descritte più avanti in questo documento.

Le implementazioni di DataSet.ReadXml e DataTable.ReadXml sono state create prima che le vulnerabilità della serializzazione fossero una categoria di minacce ben nota. Di conseguenza, il codice non segue le procedure consigliate di sicurezza correnti. Queste API possono essere usate come vettori per gli utenti malintenzionati che vogliono eseguire attacchi DoS contro le app Web. Questi attacchi potrebbero rendere il servizio Web non reattivo o causare la terminazione inaspettata del processo. Il framework non fornisce mitigazioni per queste categorie di attacchi e .NET considera questo comportamento "normale".

.NET ha rilasciato aggiornamenti della sicurezza per attenuare alcuni problemi, ad esempio la diffusione di informazioni o l'esecuzione di codice remoto in DataSet.ReadXml e DataTable.ReadXml. Gli aggiornamenti della sicurezza .NET potrebbero non fornire una protezione completa da queste categorie di minacce. Gli utenti devono valutare i singoli scenari e considerare la potenziale esposizione a questi rischi.

Gli utenti devono tenere presente che gli aggiornamenti della sicurezza per queste API possono influire sulla compatibilità delle applicazioni in alcune situazioni. Inoltre, esiste la possibilità che venga individuata una nuova vulnerabilità in queste API per la quale .NET non può pubblicare un aggiornamento della sicurezza.

Si consiglia agli utenti di queste API di:

  • Valutare l'opportunità di usare una delle alternative descritte più avanti in questo documento.
  • Eseguire valutazioni dei singoli rischi nelle app.

È responsabilità esclusiva dell'utente determinare se utilizzare queste API. Gli utenti devono valutare eventuali rischi di sicurezza, tecnici e legali, inclusi i requisiti normativi, che possono accompagnare l'uso di queste API.

DataSet e DataTable tramite i servizi Web ASP.NET o WCF

È possibile accettare un'istanza di DataSet o una di DataTable in un servizio Web ASP.NET (SOAP), come illustrato nel codice seguente:

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 variante è quella di non accettare DataSet o DataTable direttamente come parametro, ma di accettarlo come parte dell'intero grafico di oggetti serializzati SOAP, come illustrato nel codice seguente:

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

In alternativa, usare WCF invece dei servizi Web 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; }
}

In tutti questi casi, il modello di minaccia e le garanzie di sicurezza sono gli stessi indicati nella sezione DataSet.ReadXml e DataTable.ReadXml.

Deserializzare un oggetto DataSet o DataTable tramite XmlSerializer

Gli sviluppatori possono usare XmlSerializer per deserializzare le istanze di DataSet e DataTable, come illustrato nel codice seguente:

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

In questi casi, il modello di minaccia e le garanzie di sicurezza sono le stesse indicate nella sezione DataSet.ReadXml e DataTable.ReadXml

Deserializzare un oggetto DataSet o DataTable tramite JsonConvert

La popolare libreria Newtonsoft di terze parti Json.NET può essere usata per deserializzare le istanze di DataSet e DataTable, come illustrato nel codice seguente:

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 deserializzazione di un oggetto DataSet o DataTable eseguita in questo modo da un BLOB JSON non attendibile non è sicura. Questo modello è vulnerabile a un attacco Denial of Service. Un attacco di questo tipo potrebbe causare l'arresto anomalo o il blocco dell'app.

Nota

Microsoft non garantisce né supporta l'implementazione di librerie di terze parti come Newtonsoft.Json. Queste informazioni vengono fornite per completezza e sono accurate al momento della stesura di questo articolo.

Deserializzare un oggetto DataSet o DataTable tramite BinaryFormatter

Non si devono mai usare BinaryFormatter, NetDataContractSerializer, SoapFormatter o i formattatori non sicuri correlati per deserializzare un'istanza di DataSet o DataTable da un payload non attendibile:

  • Ciò è soggetto a un attacco completo di esecuzione di codice remoto.
  • L'uso di un oggetto SerializationBinder personalizzato non è sufficiente per evitare un attacco di questo tipo.

Sostituzioni sicure

Per le app che:

  • Accettano DataSet o DataTable tramite un endpoint SOAP con estensione asmx o un endpoint WCF.
  • Deserializzare i dati non attendibili in un'istanza di DataSet o DataTable.

Valutare l'opportunità di sostituire il modello a oggetti per usare Entity Framework. Entity Framework:

  • È un framework avanzato, moderno e orientato agli oggetti che può rappresentare i dati relazionali.
  • Offre un ecosistema diversificato di provider di database per semplificare la progettazione di query di database tramite i modelli a oggetti di Entity Framework.
  • Offre protezioni predefinite durante la deserializzazione dei dati da origini non attendibili.

Per le app che usano gli endpoint SOAP .aspx, è consigliabile modificare tali endpoint per l'uso di WCF. WCF è una sostituzione più completa per i servizi Web .asmx. Gli endpoint WCF possono essere esposti tramite SOAP per garantire la compatibilità con i chiamanti esistenti.

Analizzatori del codice

Le regole di sicurezza dell'analizzatore del codice, che vengono eseguite quando il codice sorgente viene compilato, possono essere utili per individuare le vulnerabilità correlate a questo problema di sicurezza nel codice C# e Visual Basic. Microsoft.CodeAnalysis.FxCopAnalyzers è un pacchetto NuGet di analizzatori di codice distribuiti in nuget.org.

Per una panoramica degli analizzatori di codice, vedere Panoramica degli analizzatori di codice sorgente.

Abilitare le regole di Microsoft.CodeAnalysis.FxCopAnalyzers seguenti:

  • CA2350: Non usare DataTable.ReadXml() con dati non attendibili
  • CA2351: Non usare DataSet.ReadXml() con dati non attendibili
  • CA2352: Un elemento DataSet o DataTable non sicuro nel tipo serializzabile può essere vulnerabile agli attacchi di esecuzione di codice remoto
  • CA2353: Elemento DataSet o DataTable non sicuro in un tipo serializzabile
  • CA2354: Un elemento DataSet o DataTable non sicuro nel grafico di oggetti deserializzato può essere vulnerabile agli attacchi di esecuzione di codice remoto
  • CA2355: Nel grafico di oggetti deserializzabile è stato trovato il tipo DataSet o DataTable non sicuro
  • CA2356: Tipo DataSet o DataTable non sicuro nel grafico di oggetti deserializzabile Web
  • CA2361: Assicurarsi che la classe generata automaticamente che contiene DataSet.ReadXml() non venga usata con dati non attendibili
  • CA2362: L'oggetto DataSet o DataTable non sicuro nel tipo serializzabile generato automaticamente può essere vulnerabile ad attacchi di tipo esecuzione di codice remoto

Per altre informazioni sulla configurazione di regole, vedere Usare gli analizzatori di codice.

Le nuove regole di sicurezza sono disponibili nei pacchetti NuGet seguenti:

  • Microsoft.CodeAnalysis.FxCopAnalyzers 3.3.0: per Visual Studio 2019 versione 16.3 o successiva
  • Microsoft.CodeAnalysis.FxCopAnalyzers 2.9.11: per Visual Studio 2017 versione 15.9 o successiva