Udostępnij za pośrednictwem


Wskazówki dotyczące zabezpieczeń zestawów danych i tabeli DataTable

Ten artykuł dotyczy:

  • .NET Framework (wszystkie wersje)
  • .NET Core i nowsze wersje
  • .NET 5 lub nowszy

Typy DataSet i DataTable to starsze składniki platformy .NET, które umożliwiają reprezentowanie zestawów danych jako obiektów zarządzanych. Te składniki zostały wprowadzone w programie .NET Framework 1.0 w ramach oryginalnej infrastruktury ADO.NET. Ich celem było zapewnienie zarządzanego widoku dla zestawu danych relacyjnych, abstrakcja, czy bazowe źródło danych to XML, SQL, czy inna technologia.

Aby uzyskać więcej informacji na temat ADO.NET, w tym bardziej nowoczesnych paradygmatów widoku danych, zobacz dokumentację ADO.NET.

Ograniczenia domyślne podczas deserializacji elementu DataSet lub DataTable z pliku XML

We wszystkich obsługiwanych wersjach programu .NET Framework, .NET Core i .NET DataSet należy DataTable umieścić następujące ograniczenia dotyczące typów obiektów, które mogą znajdować się w deserializacji danych. Domyślnie ta lista jest ograniczona do:

  • Odpowiedniki pierwotne i pierwotne: bool, , charSqlInt32sbytedecimaldoublefloatulongDateTimelonguintintDateTimeOffsetushortshortbyteTimeSpanstringSqlCharsSqlBytesSqlDateTimeSqlByteSqlDecimalSqlBooleanSqlDoubleSqlGuidSqlBinaryGuidSqlInt64SqlMoneySqlInt16SqlSinglei .SqlString
  • Często używane nietypowe: Type, Urii BigInteger.
  • Często używane typy System.Drawing: Color, , Point, RectanglePointF, RectangleF, Size, i SizeF.
  • Enum Typy.
  • Tablice i listy powyższych typów.

Jeśli przychodzące dane XML zawierają obiekt, którego typ nie znajduje się na tej liście:

  • Zgłaszany jest wyjątek z następującym komunikatem i śladem stosu. Komunikat o błędzie: System.InvalidOperationException: typ "<Nazwa> typu, Version=<n.n.n>., Culture=<culture>, PublicKeyToken=<token value>" nie jest dozwolony w tym miejscu. Ślad stosu: at System.Data.TypeLimiter.EnsureTypeIsAllowed(Type, TypeLimiter capturedLimiter) at System.Data.DataColumn.UpdateColumnType(Type, StorageType TypeCode) w System.Data.DataColumn.set_DataType(wartość typu)

  • Operacja deserializacji kończy się niepowodzeniem.

Podczas ładowania kodu XML do istniejącego DataSet DataTable wystąpienia uwzględniane są również istniejące definicje kolumn. Jeśli tabela zawiera już definicję kolumny typu niestandardowego, ten typ jest tymczasowo dodawany do listy dozwolonych na czas trwania operacji deserializacji XML.

Uwaga

Po dodaniu kolumn do DataTableReadXml elementu element nie odczytuje schematu z pliku XML, a jeśli schemat nie jest zgodny, nie będzie również odczytywany w rekordach, dlatego należy dodać wszystkie kolumny samodzielnie, aby użyć tej metody.

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

Ograniczenia typu obiektu mają zastosowanie również w przypadku używania XmlSerializer w celu deserializacji wystąpienia klasy DataSet lub DataTable. Mogą jednak nie mieć zastosowania w przypadku używania BinaryFormatter funkcji do deserializacji wystąpienia klasy DataSet lub DataTable.

Ograniczenia typu obiektu nie mają zastosowania w przypadku używania elementu DataAdapter.Fill, na przykład gdy DataTable wystąpienie jest wypełniane bezpośrednio z bazy danych bez używania interfejsów API deserializacji XML.

Rozszerzanie listy dozwolonych typów

Aplikacja może rozszerzyć listę dozwolonych typów, aby uwzględnić typy niestandardowe oprócz wbudowanych typów wymienionych powyżej. W przypadku rozszerzania listy dozwolonych typów zmiana ma wpływ na wszystkie DataSet wystąpienia i DataTable w aplikacji. Nie można usunąć typów z listy typów wbudowanych dozwolonych.

Rozszerzanie konfiguracji (.NET Framework 4.0 i nowsze)

Plik App.config może służyć do rozszerzania listy dozwolonych typów. Aby rozszerzyć listę dozwolonych typów:

  • Użyj elementu , <configSections> aby dodać odwołanie do sekcji Konfiguracji System.Data .
  • Użyj <system.data.dataset.serialization>/<allowedTypes> polecenia , aby określić dodatkowe typy.

Każdy <add> element musi określać tylko jeden typ przy użyciu nazwy kwalifikowanego typu zestawu. Aby dodać dodatkowe typy do listy dozwolonych typów, użyj wielu <add> elementów.

W poniższym przykładzie pokazano rozszerzenie listy dozwolonych typów przez dodanie typu Fabrikam.CustomTypeniestandardowego .

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

Aby pobrać kwalifikowaną nazwę zestawu typu, użyj właściwości Type.AssemblyQualifiedName , jak pokazano w poniższym kodzie.

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

Rozszerzanie konfiguracji (.NET Framework 2.0 – 3.5)

Jeśli aplikacja jest przeznaczona dla programu .NET Framework 2.0 lub 3.5, nadal możesz użyć powyższego mechanizmu App.config , aby rozszerzyć listę dozwolonych typów. Jednak element <configSections> będzie wyglądać nieco inaczej, jak pokazano w poniższym kodzie:

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

Programowe rozszerzanie (.NET Framework, .NET Core, .NET 5+)

Listę dozwolonych typów można również rozszerzyć programowo przy użyciu parametru AppDomain.SetData z dobrze znanym kluczem System.Data.DataSetDefaultAllowedTypes, jak pokazano w poniższym kodzie.

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

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

W przypadku korzystania z mechanizmu rozszerzenia wartość skojarzona z kluczem System.Data.DataSetDefaultAllowedTypes musi być typu Type[].

W programie .NET Framework lista dozwolonych typów może zostać rozszerzona zarówno przy użyciu pliku App.config , jak i AppDomain.SetData. W takim przypadku obiekt DataTable będzie deserializowany jako część danych, DataSet jeśli jego typ znajduje się na obu listach.

Uruchamianie aplikacji w trybie inspekcji (.NET Framework)

W programie .NET Framework DataSet i DataTable zapewniają możliwość trybu inspekcji. Gdy tryb inspekcji jest włączony, DataSet i DataTable porównaj typy obiektów przychodzących z listy dozwolonych typów. Jeśli jednak obiekt, którego typ jest niedozwolony, nie zostanie zgłoszony wyjątek. Zamiast tego należy DataTable powiadomić wszystkie dołączone TraceListener wystąpienia o tym, DataSet że istnieje podejrzany typ, co umożliwi TraceListener rejestrowanie tych informacji. Nie jest zgłaszany wyjątek, a operacja deserializacji jest kontynuowana.

Ostrzeżenie

Uruchamianie aplikacji w trybie inspekcji powinno być tylko tymczasową miarą używaną do testowania. Gdy tryb inspekcji jest włączony DataSet i DataTable nie wymuszaj ograniczeń typu, które mogą wprowadzać dziurę zabezpieczeń wewnątrz aplikacji. Aby uzyskać więcej informacji, zobacz sekcje zatytułowane Usuwanie wszystkich ograniczeń typu i Bezpieczeństwo w odniesieniu do niezaufanych danych wejściowych.

Tryb inspekcji można włączyć za pomocą pliku App.config:

  • Zobacz sekcję Rozszerzanie konfiguracji w tym dokumencie, aby uzyskać informacje na temat odpowiedniej wartości, która ma być umieszczona <configSections> dla elementu.
  • Użyj <allowedTypes auditOnly="true"> polecenia , aby włączyć tryb inspekcji, jak pokazano w poniższym znaczniku.
<?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>

Po włączeniu trybu inspekcji możesz użyć pliku App.config, aby połączyć DataSet TraceListener preferowaną z wbudowanym TraceSource. nazwą wbudowanego źródła śledzenia jest System.Data.DataSet. W poniższym przykładzie pokazano zapisywanie zdarzeń śledzenia w konsoli programu i pliku dziennika na dysku.

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

Aby uzyskać więcej informacji na temat TraceSource elementów i TraceListener, zobacz dokument Instrukcje: używanie elementu TraceSource i filtrów z odbiornikami śledzenia.

Uwaga

Uruchamianie aplikacji w trybie inspekcji nie jest dostępne na platformie .NET Core lub w programie .NET 5 lub nowszym.

Usuń wszystkie ograniczenia typu

Jeśli aplikacja musi usunąć wszystkie ograniczenia ograniczania typów z DataSet i DataTable:

  • Istnieje kilka opcji pomijania ograniczeń ograniczania typów.
  • Dostępne opcje zależą od struktury docelowej aplikacji.

Ostrzeżenie

Usunięcie wszystkich ograniczeń typu może wprowadzić dziurę zabezpieczeń wewnątrz aplikacji. W przypadku korzystania z tego mechanizmu upewnij się, że aplikacja nie używa DataSet ani DataTable nie odczytuje niezaufanych danych wejściowych. Aby uzyskać więcej informacji, zobacz CVE-2020-1147 i następującą sekcję zatytułowaną Bezpieczeństwo w odniesieniu do niezaufanych danych wejściowych.

Za pomocą konfiguracji aplikacji AppContext (program .NET Framework 4.6 lub nowszy, .NET Core 2.1 i nowsze wersje, .NET 5 i nowsze)

Przełącznik AppContext , Switch.System.Data.AllowArbitraryDataSetTypeInstantiationpo ustawieniu na wartość true , usuwa wszystkie ograniczenia ograniczania typów z DataSet i DataTable.

W programie .NET Framework ten przełącznik można włączyć za pośrednictwem pliku App.config, jak pokazano w następującej konfiguracji:

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

W ASP.NET <AppContextSwitchOverrides> element jest niedostępny. Zamiast tego przełącznik można włączyć za pośrednictwem pliku Web.config, jak pokazano w następującej konfiguracji:

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

Aby uzyskać więcej informacji, zobacz element AppContextSwitchOverrides>.<

W programie .NET Core, .NET 5 i ASP.NET Core to ustawienie jest kontrolowane przez runtimeconfig.json, jak pokazano w następującym formacie JSON:

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

Aby uzyskać więcej informacji, zobacz ".NET Core runtime configuration settings" (Ustawienia konfiguracji środowiska uruchomieniowego platformy .NET Core).

AllowArbitraryDataSetTypeInstantiation Można również ustawić programowo za pomocą pliku konfiguracji AppContext.SetSwitch , jak pokazano w poniższym kodzie:

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

W przypadku wybrania powyższego podejścia programowego wywołanie AppContext.SetSwitch powinno nastąpić na wczesnym etapie uruchamiania aplikacji.

Za pośrednictwem rejestru całego komputera (.NET Framework 2.0 – 4.x)

Jeśli AppContext nie jest dostępna, kontrole ograniczania typów można wyłączyć w rejestrze systemu Windows:

  • Administrator musi skonfigurować rejestr.
  • Korzystanie z rejestru jest zmianą dla całej maszyny i będzie miało wpływ na wszystkie aplikacje uruchomione na maszynie.
Type Wartość
Klucz rejestru HKLM\SOFTWARE\Microsoft\.NETFramework\AppContext
Nazwa wartości Switch.System.Data.AllowArbitraryDataSetTypeInstantiation
Typ wartości REG_SZ
Dane wartości true

W 64-bitowym systemie operacyjnym należy dodać tę wartość dla 64-bitowego klucza (pokazanego powyżej) i 32-bitowego klucza. Klucz 32-bitowy znajduje się w lokalizacji HKLM\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\AppContext.

Aby uzyskać więcej informacji na temat konfigurowania AppContextrejestru, zobacz "AppContext dla użytkowników biblioteki".

Bezpieczeństwo w odniesieniu do niezaufanych danych wejściowych

Chociaż DataSet i DataTable nakładają domyślne ograniczenia dotyczące typów, które mogą być obecne podczas deserializacji ładunków XML, DataSet i DataTable są ogólnie nie bezpieczne, gdy są wypełniane niezaufanymi danymi wejściowymi. Poniżej znajduje się niewyczerpująca lista sposobów odczytywania DataSet niezaufanych danych wejściowych przez wystąpienie lub DataTable .

  • Obiekt DataAdapter odwołuje się do bazy danych, a DataAdapter.Fill metoda służy do wypełniania DataSet obiektu zawartością zapytania bazy danych.
  • Metoda DataSet.ReadXml or DataTable.ReadXml służy do odczytywania pliku XML zawierającego informacje o kolumnie i wierszu.
  • Wystąpienie DataSet lub DataTable jest serializowane w ramach usług internetowych ASP.NET (SOAP) lub punktu końcowego programu WCF.
  • Serializator, taki jak XmlSerializer , służy do deserializacji DataSet wystąpienia lub DataTable ze strumienia XML.
  • Serializator, taki jak JsonConvert , służy do deserializacji DataSet wystąpienia lub DataTable ze strumienia JSON. JsonConvertjest metodą w popularnej bibliotece Newtonsoft.Json innej firmy.
  • Serializator, taki jak BinaryFormatter , służy do deserializacji DataSet wystąpienia lub DataTable z nieprzetworzonego strumienia bajtów.

W tym dokumencie omówiono zagadnienia dotyczące bezpieczeństwa w poprzednich scenariuszach.

Użyj DataAdapter.Fill polecenia , aby wypełnić element DataSet z niezaufanego źródła danych

Wystąpienie DataSet można wypełnić DataAdapter przy użyciu DataAdapter.Fill metody , jak pokazano w poniższym przykładzie.

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

(Powyższy przykład kodu jest częścią większej próbki znalezionej w Wypełnianie elementu DataSet z elementu DataAdapter).

Większość aplikacji może uprościć i zakładać, że ich warstwa bazy danych jest zaufana. Jeśli jednak jesteś w zwyczaju modelowania zagrożeń w aplikacjach, model zagrożenia może rozważyć granicę zaufania między aplikacją (klientem) i warstwą bazy danych (serwer). Korzystanie z wzajemnego uwierzytelniania lub uwierzytelniania usługi AAD między klientem a serwerem jest jednym ze sposobów rozwiązywania problemów związanych z tym ryzykiem. W pozostałej części tej sekcji omówiono możliwy wynik połączenia klienta z niezaufanym serwerem.

Konsekwencje wskazywania DataAdapter elementu w niezaufanym źródle danych zależą od implementacji DataAdapter samego źródła danych.

SqlDataAdapter

W przypadku wbudowanego typu SqlDataAdapter odwołanie do niezaufanego źródła danych może spowodować atak typu "odmowa usługi" (DoS). Atak DoS może spowodować, że aplikacja nie odpowiada lub ulega awarii. Jeśli osoba atakująca może umieścić bibliotekę DLL obok aplikacji, może również być w stanie osiągnąć lokalne wykonywanie kodu.

Inne typy dataAdapter

Implementacje innych firm DataAdapter muszą dokonać własnych ocen dotyczących gwarancji bezpieczeństwa, jakie zapewniają w obliczu niezaufanych danych wejściowych. Platforma .NET nie może zagwarantować bezpieczeństwa tych implementacji.

DataSet.ReadXml i DataTable.ReadXml

Metody DataSet.ReadXml i DataTable.ReadXml nie są bezpieczne w przypadku użycia z niezaufanymi danymi wejściowymi. Zdecydowanie zalecamy, aby konsumenci zamiast tego rozważyli użycie jednej z alternatyw opisanych w dalszej części tego dokumentu.

Implementacje DataSet.ReadXml elementów i DataTable.ReadXml zostały pierwotnie utworzone przed serializacji lukami w zabezpieczeniach były dobrze zrozumiałą kategorią zagrożeń. W związku z tym kod nie stosuje bieżących najlepszych rozwiązań w zakresie zabezpieczeń. Te interfejsy API mogą służyć jako wektory do przeprowadzania ataków typu DoS na aplikacje internetowe. Te ataki mogą spowodować brak odpowiedzi usługi internetowej lub spowodować nieoczekiwane zakończenie procesu. Struktura nie zapewnia środków zaradczych dla tych kategorii ataków, a platforma .NET uważa to zachowanie za "według projektu".

Platforma .NET opublikowała aktualizacje zabezpieczeń, aby rozwiązać niektóre problemy, takie jak ujawnienie informacji lub zdalne wykonywanie kodu w usługach DataSet.ReadXml i DataTable.ReadXml. Aktualizacje zabezpieczeń platformy .NET mogą nie zapewnić pełnej ochrony przed tymi kategoriami zagrożeń. Konsumenci powinni ocenić swoje indywidualne scenariusze i rozważyć potencjalne narażenie na te zagrożenia.

Użytkownicy powinni pamiętać, że aktualizacje zabezpieczeń tych interfejsów API mogą mieć wpływ na zgodność aplikacji w niektórych sytuacjach. Ponadto istnieje możliwość wykrycia nowej luki w zabezpieczeniach tych interfejsów API, dla której platforma .NET nie może praktycznie opublikować aktualizacji zabezpieczeń.

Zalecamy, aby użytkownicy tych interfejsów API:

  • Rozważ użycie jednej z alternatyw opisanych w dalszej części tego dokumentu.
  • Przeprowadzanie indywidualnych ocen ryzyka w aplikacjach.

Jedynym zadaniem konsumenta jest określenie, czy korzystać z tych interfejsów API. Konsumenci powinni ocenić wszelkie zagrożenia bezpieczeństwa, techniczne i prawne, w tym wymagania prawne, które mogą towarzyszyć przy użyciu tych interfejsów API.

Zestaw danych i dataTable za pośrednictwem usług internetowych ASP.NET lub WCF

Istnieje możliwość zaakceptowania DataSet wystąpienia lub DataTable w usłudze internetowej ASP.NET (SOAP), jak pokazano w poniższym kodzie:

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

Odmiana tego nie jest akceptowana DataSet lub DataTable bezpośrednio jako parametr, ale zamiast tego akceptowana jako część ogólnego grafu obiektów serializowanego protokołu SOAP, jak pokazano w poniższym kodzie:

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

Możesz też użyć programu WCF zamiast ASP.NET usług internetowych:

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

We wszystkich tych przypadkach model zagrożeń i gwarancje zabezpieczeń są takie same jak w sekcji DataSet.ReadXml i DataTable.ReadXml.

Deserializowanie elementu DataSet lub DataTable za pomocą elementu XmlSerializer

Deweloperzy mogą używać XmlSerializer do deserializacji DataSet i DataTable wystąpień, jak pokazano w poniższym kodzie:

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

W takich przypadkach model zagrożeń i gwarancje bezpieczeństwa są takie same jak sekcja DataSet.ReadXml i DataTable.ReadXml

Deserializowanie elementu DataSet lub DataTable za pomocą pliku JsonConvert

Popularna biblioteka Newtonsoft innej firmy Json.NET może służyć do deserializacji DataSet i DataTable wystąpień, jak pokazano w poniższym kodzie:

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

Deserializowanie obiektu DataSet blob JSON lub DataTable w ten sposób nie jest bezpieczne. Ten wzorzec jest podatny na atak typu "odmowa usługi". Taki atak może spowodować awarię aplikacji lub uniemożliwić jej działanie.

Uwaga

Firma Microsoft nie gwarantuje ani nie obsługuje implementacji bibliotek innych firm, takich jak Newtonsoft.Json. Te informacje są dostarczane do kompletności i są dokładne w czasie pisania.

Deserializowanie elementu DataSet lub DataTable za pomocą elementu BinaryFormatter

Do deserializacji wystąpienia lub z niezaufanego ładunku nigdy nie należy używać BinaryFormatterplików , SoapFormatterNetDataContractSerializer, ani powiązanych niebezpiecznych formatów:DataTable DataSet

  • Jest to podatne na atak pełnego zdalnego wykonywania kodu.
  • Użycie niestandardowego SerializationBinder elementu nie jest wystarczające, aby zapobiec takiemu atakowi.

Bezpieczne wymiany

W przypadku aplikacji, które:

  • Zaakceptuj DataSet lub DataTable za pośrednictwem punktu końcowego protokołu SOAP asmx lub punktu końcowego programu WCF.
  • Deserializowanie niezaufanych danych w wystąpieniu DataSet klasy lub DataTable.

Rozważ zastąpienie modelu obiektów do używania programu Entity Framework. Entity Framework:

  • To bogata, nowoczesna, zorientowana na obiekt struktura, która może reprezentować dane relacyjne.
  • Oferuje zróżnicowany ekosystem dostawców baz danych, aby ułatwić projektowanie zapytań bazy danych za pośrednictwem modeli obiektów programu Entity Framework.
  • Oferuje wbudowane zabezpieczenia podczas deserializacji danych z niezaufanych źródeł.

W przypadku aplikacji korzystających z .aspx punktów końcowych protokołu SOAP rozważ zmianę tych punktów końcowych w celu korzystania z usługi WCF. WCF to bardziej w pełni funkcjonalna zamiana .asmx usług internetowych. Punkty końcowe programu WCF można uwidocznić za pośrednictwem protokołu SOAP w celu zachowania zgodności z istniejącymi obiektami wywołującymi.

Analizatory kodu

Reguły zabezpieczeń analizatora kodu, które są uruchamiane po skompilowaniu kodu źródłowego, mogą pomóc w znalezieniu luk w zabezpieczeniach związanych z tym problemem z zabezpieczeniami w kodzie C# i Visual Basic. Microsoft.CodeAnalysis.FxCopAnalyzers to pakiet NuGet analizatorów kodu dystrybuowanych na nuget.org.

Aby zapoznać się z omówieniem analizatorów kodu, zobacz Omówienie analizatorów kodu źródłowego.

Włącz następujące reguły Microsoft.CodeAnalysis.FxCopAnalyzers:

  • CA2350: Nie używaj elementu DataTable.ReadXml() z niezaufanymi danymi
  • CA2351: Nie używaj elementu DataSet.ReadXml() z niezaufanymi danymi
  • CA2352: Niebezpieczny element DataSet lub DataTable w typie z możliwością serializacji może być narażony na ataki zdalnego wykonywania kodu
  • CA2353: Niebezpieczny zestaw danych lub dataTable w typie z możliwością serializacji
  • CA2354: Niebezpieczny element DataSet lub DataTable w deserializowanym grafie obiektu może być narażony na ataki zdalnego wykonywania kodu
  • CA2355: Niebezpieczny typ DataSet lub DataTable znaleziony na grafie obiektów deserializowalnych
  • CA2356: Niebezpieczny typ DataSet lub DataTable w internetowym deserializowalnym grafie obiektu
  • CA2361: Upewnij się, że automatycznie wygenerowana klasa zawierająca klasę DataSet.ReadXml() nie jest używana z niezaufanymi danymi
  • CA2362: Niebezpieczny element DataSet lub DataTable w automatycznie wygenerowanym typie serializowalnym może być narażony na ataki zdalnego wykonywania kodu

Aby uzyskać więcej informacji na temat konfigurowania reguł, zobacz Używanie analizatorów kodu.

Nowe reguły zabezpieczeń są dostępne w następujących pakietach NuGet:

  • Microsoft.CodeAnalysis.FxCopAnalyzers 3.3.0: dla programu Visual Studio 2019 w wersji 16.3 lub nowszej
  • Microsoft.CodeAnalysis.FxCopAnalyzers 2.9.11: dla programu Visual Studio 2017 w wersji 15.9 lub nowszej