DataSet- und DataTable-Sicherheitsleitfaden

Dieser Artikel gilt für:

  • .NET Framework (alle Versionen)
  • .NET Core und höher
  • .NET 5 und höher

Die Typen DataSet und DataTable sind .NET-Legacykomponenten, die die Darstellung von Datasets als verwaltete Objekte ermöglichen. Diese Komponenten wurden in .NET Framework 1.0 als Teil der ursprünglichen ADO.NET-Infrastruktur eingeführt. Ihr Ziel war es, eine verwaltete Ansicht für ein relationales Dataset bereitzustellen und dabei den Typ der zugrunde liegenden Quelle der Daten (XML, SQL oder eine andere Technologie) zu abstrahieren.

Weitere Informationen zu ADO.NET, einschließlich modernerer Datenansichtsparadigmen, finden Sie in der ADO.NET-Dokumentation.

Standardeinschränkungen beim Deserialisieren eines DataSet oder einer DataTable aus XML

Bei allen unterstützten Versionen von .NET Framework, .NET Core und .NET gelten für DataSet und DataTable die folgenden Einschränkungen bezüglich der Objekttypen, die in den deserialisierten Daten vorhanden sein können. Diese Liste ist standardmäßig auf Folgendes beschränkt:

  • Primitive Typen und Entsprechungen von primitiven Typen: 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 und SqlString
  • Häufig verwendete nicht primitive Typen: Type, Uri und BigInteger
  • Häufig verwendete System.Drawing-Typen: Color, Point, PointF, Rectangle, RectangleF, Size und SizeF
  • Enum-Typen
  • Arrays und Listen der oben genannten Typen

Wenn die eingehenden XML-Daten ein Objekt enthalten, dessen Typ nicht in dieser Liste enthalten ist, geschieht Folgendes:

  • Eine Ausnahme mit der folgenden Meldung und Stapelüberwachung wird ausgelöst. Fehlermeldung: System.InvalidOperationException: Der Typ „<Typname>, Version=<n.n.n.n>, Culture=<Kultur>, PublicKeyToken=<Tokenwert>“ ist hier nicht zulässig. Stapelüberwachung: bei System.Data.TypeLimiter.EnsureTypeIsAllowed(Typ „type“, TypeLimiter capturedLimiter) bei System.Data.DataColumnType(Typ „type“, StorageType typeCode) bei System.Data.DataColumn.set_DataType(Typwert)

  • Der Deserialisierungsvorgang schlägt fehl.

Beim Laden von XML in eine vorhandene DataSet- oder DataTable-Instanz werden auch die vorhandenen Spaltendefinitionen berücksichtigt. Wenn die Tabelle bereits eine Spaltendefinition eines benutzerdefinierten Typs enthält, wird dieser Typ für die Dauer des XML-Deserialisierungsvorgangs vorübergehend der Liste zulässiger Typen hinzugefügt.

Hinweis

Sobald Sie einer DataTable Spalten hinzufügen, liest ReadXml das Schema nicht aus der XML-Datei. Wenn das Schema nicht übereinstimmt, werden auch die Datensätze nicht gelesen, sodass Sie alle Spalten selbst hinzufügen müssen, um diese Methode verwenden zu können.

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

Die Objekttypeinschränkungen gelten auch, wenn XmlSerializer zum Deserialisieren einer DataSet- oder DataTable-Instanz verwendet wird. Sie gelten jedoch möglicherweise nicht, wenn BinaryFormatter zum Deserialisieren einer DataSet- oder DataTable-Instanz verwendet wird.

Die Objekttypeinschränkungen gelten nicht bei Verwendung von DataAdapter.Fill, z. B. wenn eine DataTable-Instanz direkt aus einer Datenbank aufgefüllt wird, ohne die XML-Deserialisierungs-APIs zu verwenden.

Erweitern der Liste zulässiger Typen

Eine App kann die Liste der zulässigen Typen erweitern, um zusätzlich zu den oben aufgeführten integrierten Typen benutzerdefinierte Typen hinzuzufügen. Wenn die Liste der zulässigen Typen erweitert wird, betrifft diese Änderung alleDataSet- und DataTable-Instanzen innerhalb der App. Typen können nicht aus der Liste der integrierten zulässigen Typen entfernt werden.

Erweitern über die Konfiguration (.NET Framework 4.0 und höher)

Die Datei App.config kann verwendet werden, um die Liste der zulässigen Typen zu erweitern. So erweitern Sie die Liste der zulässigen Typen:

  • Verwenden Sie das <configSections>-Element, um einen Verweis auf den Konfigurationsabschnitt System.Data hinzuzufügen.
  • Verwenden Sie <system.data.dataset.serialization>/<allowedTypes>, um zusätzliche Typen anzugeben.

Jedes <add>-Element darf nur einen Typ anhand seines Typnamens mit Assemblyqualifikation angeben. Verwenden Sie mehrere <add>-Elemente, um der Liste der zulässigen Typen weitere Typen hinzuzufügen.

Das folgende Beispiel zeigt, wie die Liste der zulässigen Typen durch Hinzufügen des benutzerdefinierten Typs Fabrikam.CustomType erweitert wird.

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

Verwenden Sie zum Abrufen des Namens mit Assemblyqualifikation eines Typs wie im folgenden Code veranschaulicht die Type.AssemblyQualifiedName-Eigenschaft.

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

Erweitern über die Konfiguration (.NET Framework 2.0 bis 3.5)

Wenn Ihre App auf .NET Framework 2.0 oder 3.5 ausgerichtet ist, können Sie weiterhin wie oben beschrieben die Datei App.config verwenden, um die Liste der zulässigen Typen zu erweitern. Ihr <configSections>-Element sieht jedoch wie im folgenden Code gezeigt etwas anders aus:

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

Programmgesteuertes Erweitern (.NET Framework, .NET Core, .NET 5 und höher)

Die Liste der zulässigen Typen kann wie im folgenden Code gezeigt auch programmgesteuert erweitert werden, indem Sie AppDomain.SetData mit dem bekannten Schlüssel System.Data.DataSetDefaultAllowedTypes verwenden.

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

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

Wenn Sie den Erweiterungsmechanismus verwenden, muss der Wert, der dem Schlüssel System.Data.DataSetDefaultAllowedTypes zugeordnet ist, vom Typ Type[] sein.

In .NET Framework kann die Liste der zulässigen Typen sowohl mit App.config als auch mit AppDomain.SetData erweitert werden. In diesem Fall ermöglichen DataSet und DataTable das Deserialisieren eines Objekts als Teil der Daten, sofern der Objekttyp in einer der Listen vorhanden ist.

Ausführen einer App im Überwachungsmodus (.NET Framework)

In .NET Framework bieten DataSet und DataTable eine Überwachungsmodusfunktion. Wenn der Überwachungsmodus aktiviert ist, vergleichen DataSet und DataTable die Typen eingehender Objekte mit der Liste der zulässigen Typen. Wenn ein Objekt mit einem nicht zulässigen Typ erkannt wird, wird jedoch keine Ausnahme ausgelöst. Stattdessen benachrichtigen DataSet und DataTable alle angefügten TraceListener-Instanzen, dass ein verdächtiger Typ vorhanden ist, sodass der TraceListener diese Informationen protokollieren kann. Es wird keine Ausnahme ausgelöst, und der Deserialisierungsvorgang wird fortgesetzt.

Warnung

Das Ausführen einer App im „Überwachungsmodus“ sollte nur eine temporäre Maßnahme zum Durchführen von Tests sein. Wenn der Überwachungsmodus aktiviert ist, erzwingen DataSet und DataTable keine Typeinschränkungen, was zu einer Sicherheitslücke in Ihrer App führen kann. Weitere Informationen finden Sie in den Abschnitten Entfernen aller Typeinschränkungen und Sicherheit in Bezug auf nicht vertrauenswürdige Eingaben.

Der Überwachungsmodus kann über App.config aktiviert werden:

  • Informationen zum richtigen Wert für das <configSections>-Element finden Sie im Abschnitt Erweitern über die Konfiguration in diesem Dokument.
  • Verwenden Sie <allowedTypes auditOnly="true"> wie im folgenden Markup gezeigt, um den Überwachungsmodus zu aktivieren.
<?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>

Nachdem der Überwachungsmodus aktiviert wurde, können Sie App.config verwenden, um ihren bevorzugten TraceListener mit der integrierten TraceSource. von DataSet zu verbinden. Der Name der integrierten Ablaufverfolgungsquelle lautet System.Data.DataSet. Das folgende Beispiel veranschaulicht das Schreiben von Ablaufverfolgungsereignissen in die Konsole und in eine Protokolldatei auf dem Datenträger.

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

Weitere Informationen zu TraceSource und TraceListener finden Sie im Dokument Vorgehensweise: Verwenden von TraceSource und Filtern für Ablaufverfolgungslistener.

Hinweis

In .NET Core oder .NET 5 und höher ist das Ausführen einer App im Überwachungsmodus nicht möglich.

Entfernen aller Typeinschränkungen

Wenn eine App alle Typeinschränkungen von DataSet und DataTable entfernen muss:

  • Es gibt mehrere Optionen zum Unterdrücken von Typeinschränkungen.
  • Die verfügbaren Optionen hängen vom Framework ab, auf das die App ausgerichtet ist.

Warnung

Das Entfernen aller Typeinschränkungen kann zu einer Sicherheitslücke innerhalb der App führen. Falls Sie diesen Mechanismus verwenden, müssen Sie sicherstellen, dass die App DataSet oder DataTablenicht zum Lesen von nicht vertrauenswürdigen Eingaben verwendet. Weitere Informationen finden Sie unter CVE-2020-1147 und im folgenden Abschnitt Sicherheit in Bezug auf nicht vertrauenswürdige Eingaben.

Über die AppContext-Konfiguration (.NET Framework 4.6 und höher, .NET Core 2.1 und höher, .NET 5 und höher)

Wenn die AppContext-Option Switch.System.Data.AllowArbitraryDataSetTypeInstantiation auf true festgelegt wird, werden alle Typeinschränkungen für DataSet und DataTable entfernt.

In .NET Framework kann diese Option wie in der folgenden Konfiguration gezeigt über App.config aktiviert werden:

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

In ASP.NET ist das <AppContextSwitchOverrides>-Element nicht verfügbar. Stattdessen kann die Option wie in der folgenden Konfiguration gezeigt über Web.config aktiviert werden:

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

Weitere Informationen finden Sie im Artikel zum <AppContextSwitchOverrides>-Element.

In .NET Core, .NET 5 und ASP.NET Core wird diese Einstellung wie im folgenden JSON-Code gezeigt durch runtimeconfig.json gesteuert:

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

Weitere Informationen finden Sie unter Konfigurationseinstellungen für die .NET Core-Runtime.

AllowArbitraryDataSetTypeInstantiation kann wie im folgenden Code gezeigt auch programmgesteuert über AppContext.SetSwitch festgelegt werden, anstatt eine Konfigurationsdatei zu verwenden:

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

Wenn Sie den obigen programmgesteuerten Ansatz verwenden, sollte der Aufruf von AppContext.SetSwitch zu einem frühen Zeitpunkt im Startvorgang der App erfolgen.

Über die computerweite Registrierung (.NET Framework 2.0 bis 4.x)

Wenn AppContext nicht verfügbar ist, können Typeinschränkungsüberprüfungen über die Windows-Registrierung deaktiviert werden:

  • Die Registrierung muss von Administrator*innen konfiguriert werden.
  • Die Verwendung der Registrierung ist eine computerweite Änderung und wirkt sich auf alle Apps aus, die auf dem Computer ausgeführt werden.
Typ Wert
Registrierungsschlüssel HKLM\SOFTWARE\Microsoft\.NETFramework\AppContext
Name des Werts Switch.System.Data.AllowArbitraryDataSetTypeInstantiation
Werttyp REG_SZ
Daten des Werts true

Bei einem 64-Bit-Betriebssystem muss dieser Wert möglicherweise sowohl für den 64-Bit-Schlüssel (siehe oben) als auch den 32-Bit-Schlüssel hinzugefügt werden. Der 32-Bit-Schlüssel befindet sich unter HKLM\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\AppContext.

Weitere Informationen zur Verwendung der Registrierung zum Konfigurieren von AppContext finden Sie unter AppContext for library consumers (AppContext für Bibliotheksbenutzer*innen).

Sicherheit in Bezug auf nicht vertrauenswürdige Eingaben

Obwohl DataSet und DataTable Standardeinschränkungen für die Typen vorgeben, die beim Deserialisieren von XML-Nutzdaten vorhanden sein dürfen, sind DataSet und DataTable generell nicht sicher, wenn sie mit nicht vertrauenswürdigen Eingaben aufgefüllt werden. In der folgenden nicht abschließenden Liste ist aufgeführt, wie eine DataSet- oder DataTable-Instanz nicht vertrauenswürdige Eingaben lesen kann.

  • Ein DataAdapter verweist auf eine Datenbank, und die DataAdapter.Fill-Methode wird verwendet, um ein DataSet mit dem Inhalt einer Datenbankabfrage aufzufüllen.
  • Die DataSet.ReadXml- oder DataTable.ReadXml-Methode wird verwendet, um eine XML-Datei mit Spalten- und Zeileninformationen zu lesen.
  • Eine DataSet- oder DataTable-Instanz wird als Teil eines ASP.NET (SOAP)-Webdiensts oder WCF-Endpunkts serialisiert.
  • Ein Serialisierungsmodul wie XmlSerializer wird verwendet, um eine DataSet- oder DataTable-Instanz aus einem XML-Stream zu deserialisieren.
  • Ein Serialisierungsmodul wie JsonConvert wird verwendet, um eine DataSet- oder DataTable-Instanz aus einem JSON-Stream zu deserialisieren. JsonConvert ist eine Methode in der beliebten Drittanbieterbibliothek Newtonsoft.Json.
  • Ein Serialisierungsmodul wie BinaryFormatter wird verwendet, um eine DataSet- oder DataTable-Instanz aus einem RAW-Bytestream zu deserialisieren.

In diesem Dokument werden Sicherheitsüberlegungen für die oben genannten Szenarien erläutert.

Verwenden von DataAdapter.Fill zum Auffüllen eines DataSet aus einer nicht vertrauenswürdigen Datenquelle

Eine DataSet-Instanz kann wie im folgenden Beispiel gezeigt mithilfe der DataAdapter-MethodeDataAdapter.Fill aus einem aufgefüllt werden.

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

(Das obige Codebeispiel ist Teil eines größeren Beispiels, das unter Auffüllen eines Datasets aus einem DataAdapter verfügbar ist.)

Die meisten Apps können durch eine Vereinfachung voraussetzen, dass ihre Datenbankebene vertrauenswürdig ist. Wenn Sie üblicherweise die Gefahrenmodellierung Ihrer Apps verwenden, geht Ihr Gefahrenmodell jedoch möglicherweise davon aus, dass eine Vertrauensstellungsgrenze zwischen der Anwendung (Client) und der Datenbankebene (Server) besteht. Die Verwendung der gegenseitigen Authentifizierung oder AAD-Authentifizierung (Azure Active Directory) zwischen Client und Server ist eine Möglichkeit, den damit einhergehenden Risiken vorzubeugen. Im Rest dieses Abschnitts wird erläutert, zu welchem Ergebnis es führen kann, wenn ein Client eine Verbindung mit einem nicht vertrauenswürdigen Server herstellt.

Welche Folgen das Verweisen eines DataAdapter auf eine nicht vertrauenswürdige Datenquelle hat, hängt von der Implementierung des DataAdapter selbst ab.

SqlDataAdapter

Für den integrierten Typ SqlDataAdapter kann das Verweisen auf eine nicht vertrauenswürdige Datenquelle zu einem Denial-of-Service-Angriff (DoS) führen. Infolge des DoS-Angriffs könnte die App nicht mehr reagieren oder abstürzen. Wenn Angreifer*innen mit der App eine DLL einschleusen können, können sie möglicherweise auch Code lokal ausführen.

Andere DataAdapter-Typen

DataAdapter-Implementierungen von Drittanbieter*innen müssen durch eigene Bewertungen bestimmen, welche Sicherheitsgarantien sie für nicht vertrauenswürdige Eingaben bieten. .NET kann keine Sicherheitsgarantien für diese Implementierungen geben.

DataSet.ReadXml und DataTable.ReadXml

Die Methoden DataSet.ReadXml und DataTable.ReadXml sind nicht sicher, wenn sie mit nicht vertrauenswürdigen Eingaben verwendet werden. Es wird dringend empfohlen, dass Benutzer*innen stattdessen die Verwendung einer der weiter unten in diesem Dokument beschriebenen Alternativen in Betracht ziehen.

Die Implementierungen von DataSet.ReadXml und DataTable.ReadXml wurden ursprünglich erstellt, als Sicherheitsrisiken im Zusammenhang mit der Serialisierung noch keine so gut erforschte Bedrohungskategorie waren. Folglich entspricht der Code nicht den aktuellen bewährten Methoden für die Sicherheit. Diese APIs können von Angreifer*innen als Vektoren verwendet werden, um DoS-Angriffe auf Web-Apps auszuführen. Diese Angriffe können dafür sorgen, dass der Webdienst nicht mehr reagiert, oder zu einer unerwarteten Prozessbeendigung führen. Das Framework bietet keine Entschärfungen für diese Angriffskategorien, und .NET betrachtet dieses Verhalten als „entwurfsbedingt“.

.NET hat Sicherheitsupdates veröffentlicht, um einige Probleme wie die Offenlegung von Informationen oder die Remoteausführung von Code in DataSet.ReadXml und DataTable.ReadXml zu beheben. Die .NET-Sicherheitsupdates bieten möglicherweise keinen vollständigen Schutz vor diesen Bedrohungskategorien. Benutzer sollten ihre individuellen Szenarios bewerten und die potenzielle Gefahr berücksichtigen, die für sie von diesen Risiken ausgeht.

Benutzer*innen sollten sich bewusst sein, dass Sicherheitsupdates für diese APIs mitunter die Anwendungskompatibilität beeinträchtigen können. Zudem besteht die Möglichkeit, dass ein neues Sicherheitsrisiko in diesen APIs entdeckt wird, für das .NET praktisch kein Sicherheitsupdate veröffentlichen kann.

Benutzer*innen dieser APIs wird empfohlen, einen der folgenden Ansätze zu verwenden:

  • Erwägen Sie, eine der weiter unten in diesem Dokument beschriebenen Alternativen zu verwenden.
  • Nehmen Sie individuelle Risikobewertungen für die Apps vor.

Die Entscheidung, ob sie diese APIs verwenden, liegt in der alleinigen Verantwortung der Benutzer*innen. Benutzer*innen sollten alle sicherheitsrelevanten, technischen und rechtlichen Risiken (einschließlich gesetzlicher Anforderungen) bewerten, die mit der Verwendung dieser APIs einhergehen können.

DataSet und DataTable über ASP.NET-Webdienste oder WCF (Windows Communication Foundation)

Eine DataSet- oder DataTable-Instanz kann wie im folgenden Code gezeigt in einem ASP.NET (SOAP)-Webdienst akzeptiert werden:

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

Eine Variation besteht wie im folgenden Code gezeigt darin, DataTable oder DataSet nicht direkt als Parameter, sondern stattdessen als Teil des gesamten serialisierten SOAP-Objektgraphen zu akzeptieren:

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

Alternativ können Sie WCF anstelle von ASP.NET-Webdiensten verwenden:

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 all diesen Fällen sind das Gefahrenmodell und die Sicherheitsgarantien mit denen im Abschnitt DataSet.ReadXml und DataTable.ReadXml identisch.

Deserialisieren eines DataSet oder einer DataTable über XmlSerializer

Entwickler*innen können wie im folgenden Code gezeigt XmlSerializer verwenden, um DataSet- und DataTable-Instanzen zu deserialisieren:

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 diesen Fällen sind das Gefahrenmodell und die Sicherheitsgarantien mit denen im Abschnitt DataSet.ReadXml und DataTable.ReadXml identisch.

Deserialisieren eines DataSet oder einer DataTable über JsonConvert

Die beliebte Newtonsoft-Drittanbieterbibliothek Json.NET kann wie im folgenden Code gezeigt zum Deserialisieren von DataSet- und DataTable-Instanzen verwendet werden:

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

Ein DataSet oder eine DataTable auf diese Weise aus einem nicht vertrauenswürdigen JSON-Blob zu deserialisieren, ist nicht sicher. Dieses Muster ist anfällig für DoS-Angriffe. Ein solcher Angriff könnte dazu führen, dass die App abstürzt oder nicht mehr reagiert.

Hinweis

Microsoft übernimmt keine Garantie oder Unterstützung für die Implementierung von Drittanbieterbibliotheken wie Newtonsoft.Json. Diese Informationen werden der Vollständigkeit halber bereitgestellt und sind zum Zeitpunkt der Erstellung dieses Dokuments korrekt.

Deserialisieren eines DataSet oder einer DataTable über BinaryFormatter

Verwenden Sie niemals BinaryFormatter, NetDataContractSerializer, SoapFormatter oder verwandte nicht sichere Formatierer, um eine DataSet- oder DataTable-Instanz aus nicht vertrauenswürdigen Nutzdaten zu deserialisieren:

  • Diese Vorgehensweise ist anfällig für Angriffe durch Remotecodeausführung.
  • Die Verwendung eines benutzerdefinierten SerializationBinder ist nicht ausreichend, um einen solchen Angriff zu verhindern.

Sichere Ersetzungen

Für Apps, die entweder:

  • DataSet oder DataTable über einen ASMX-SOAP-Endpunkt oder einen WCF-Endpunkt akzeptieren
  • Nicht vertrauenswürdige Daten in eine Instanz von DataSet oder DataTable deserialisieren

Erwägen Sie, das Objektmodell zu ersetzen und stattdessen Entity Framework zu verwenden. Entity Framework:

  • Ist ein umfangreiches, modernes, objektorientiertes Framework, das relationale Daten darstellen kann
  • Ermöglicht es Ihnen dank eines vielfältigen Ökosystems von Datenbankanbieter*innen, Datenbankabfragen ganz einfach über Ihre Entity Framework-Objektmodelle zu projizieren
  • Bietet integrierte Schutzmaßnahmen beim Deserialisieren von Daten aus nicht vertrauenswürdigen Quellen

Für Apps, die .aspx-SOAP-Endpunkte verwenden, sollten Sie diese Endpunkte ggf. ändern, um WCF zu verwenden. WCF ist ein Ersatz für .asmx-Webdienste, der mehr Features bietet. Sie können WCF-Endpunkte zum Gewährleisten der Kompatibilität mit vorhandenen Aufrufern über SOAP verfügbar machen.

Codeanalysetools

Sicherheitsregeln des Codeanalysetools, die beim Kompilieren Ihres Quellcodes ausgeführt werden, können helfen, mit diesem Sicherheitsproblem zusammenhängende Sicherheitsrisiken in C#- und Visual Basic-Code zu finden. Microsoft.CodeAnalysis.FxCopAnalyzers ist ein NuGet-Paket von Codeanalysetools, das auf nuget.org verteilt wird.

Eine Übersicht über Codeanalysetools finden Sie unter Übersicht über Quellcode-Analysetools.

Aktivieren Sie die folgenden Microsoft.CodeAnalysis.FxCopAnalyzers-Regeln:

  • CA2350: DataTable.ReadXml() nicht mit nicht vertrauenswürdigen Daten verwenden
  • CA2351: DataSet.ReadXml() nicht mit nicht vertrauenswürdigen Daten verwenden
  • CA2352: Ein unsicheres DataSet- oder DataTable-Element in einem serialisierbaren Typ kann für Angriffe durch Remotecodeausführung anfällig sein.
  • CA2353: Unsicheres DataSet oder unsichere DataTable in serialisierbarem Typ
  • CA2354: Ein unsicherer DataSet- oder DataTable-Typ in einem deserialisierten Objektgraph kann für Angriffe durch Remotecodeausführung anfällig sein.
  • CA2355: Unsicherer DataSet- oder DataTable-Typ in deserialisiertem Objektgraph gefunden
  • CA2356: Unsicherer DataSet- oder DataTable-Typ in webserialisiertem Objektgraph
  • CA2361: Sicherstellen, dass die automatisch generierte Klasse mit DataSet.ReadXml() nicht mit nicht vertrauenswürdigen Daten verwendet wird
  • CA2362: Ein unsicheres DataSet- oder DataTable-Element in einem automatisch generierten, serialisierbaren Typ kann für Angriffe durch Remotecodeausführung anfällig sein.

Weitere Informationen zum Konfigurieren von Regeln finden Sie unter Verwenden von Codeanalysetools.

Die neuen Sicherheitsregeln sind in den folgenden NuGet-Paketen verfügbar:

  • Microsoft.CodeAnalysis.FxCopAnalyzers 3.3.0: für Visual Studio 2019 Version 16.3 oder höher
  • Microsoft.CodeAnalysis.FxCopAnalyzers 2.9.11: für Visual Studio 2017 Version 15.9 oder höher