Sdílet prostřednictvím


CA2329: Ne deserializovat pomocí JsonSerializer pomocí nezabezpečené konfigurace

Vlastnost Hodnota
ID pravidla CA2329
Název Nepoužívejte s JsonSerializer deserializaci pomocí nezabezpečené konfigurace
Kategorie Zabezpečení
Oprava způsobující chybu nebo chybu způsobující chybu Nenarušující
Povoleno ve výchozím nastavení v .NET 8 No

Příčina

Toto pravidlo se aktivuje, pokud platí obě následující podmínky pro instanci Newtonsoft.JsonSerializer , která je předána metodě deserializace nebo inicializována jako pole nebo vlastnost:

Ve výchozím nastavení toto pravidlo analyzuje celý základ kódu, ale dá se nakonfigurovat.

Popis pravidla

Nezabezpečené deserializátory jsou zranitelné při deserializaci nedůvěryhodných dat. Útočník by mohl serializovaná data upravit tak, aby zahrnovala neočekávané typy pro vložení objektů se škodlivými vedlejšími účinky. Útok na nezabezpečený deserializátor může například spouštět příkazy v podkladovém operačním systému, komunikovat přes síť nebo odstraňovat soubory.

Toto pravidlo vyhledá instance Newtonsoft.JsonSerializer nakonfigurované tak, aby deserializovaly typy zadané ze vstupu, ale nebyly nakonfigurovány tak, aby omezovaly deserializované typy pomocí Newtonsoft.Json.Serialization.ISerializationBinder. Pokud chcete zakázat deserializaci typů zadaných ze vstupu, zakažte pravidla CA2327, CA2328, CA2329 a CA2330 a místo toho povolte pravidlo CA2326.

Jak opravit porušení

Kdy potlačit upozornění

Upozornění z tohoto pravidla je bezpečné potlačit, pokud:

  • Víte, že vstup je důvěryhodný. Vezměte v úvahu, že hranice důvěryhodnosti vaší aplikace a toky dat se můžou v průběhu času měnit.
  • Provedli jste jedno z bezpečnostních opatření v části Jak opravit porušení.

Potlačení upozornění

Pokud chcete pouze potlačit jedno porušení, přidejte do zdrojového souboru direktivy preprocesoru, abyste pravidlo zakázali a znovu povolili.

#pragma warning disable CA2329
// The code that's violating the rule is on this line.
#pragma warning restore CA2329

Pokud chcete pravidlo pro soubor, složku nebo projekt zakázat, nastavte jeho závažnost v none konfiguračním souboru.

[*.{cs,vb}]
dotnet_diagnostic.CA2329.severity = none

Další informace naleznete v tématu Jak potlačit upozornění analýzy kódu.

Konfigurace kódu pro analýzu

Pomocí následujících možností můžete nakonfigurovat, pro které části základu kódu se má toto pravidlo spouštět.

Tyto možnosti můžete nakonfigurovat jenom pro toto pravidlo, pro všechna pravidla, která platí, nebo pro všechna pravidla v této kategorii (zabezpečení), na která platí. Další informace naleznete v tématu Možnosti konfigurace pravidla kvality kódu.

Vyloučení konkrétních symbolů

Z analýzy můžete vyloučit konkrétní symboly, jako jsou typy a metody. Pokud chcete například určit, že pravidlo by se nemělo spouštět u žádného kódu v rámci pojmenovaných MyTypetypů, přidejte do souboru .editorconfig v projektu následující dvojici klíč-hodnota:

dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType

Povolené formáty názvů symbolů v hodnotě možnosti (oddělené ):|

  • Pouze název symbolu (zahrnuje všechny symboly s názvem bez ohledu na typ nebo obor názvů).
  • Plně kvalifikované názvy ve formátu ID dokumentace symbolu. Každý název symbolu vyžaduje předponu typu symbolu, například M: pro metody, T: typy a N: obory názvů.
  • .ctor pro konstruktory a .cctor statické konstruktory.

Příklady:

Hodnota možnosti Shrnutí
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType Odpovídá všem symbolům s názvem MyType.
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 Porovná všechny symboly pojmenované buď MyType1 nebo MyType2.
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) Odpovídá konkrétní metodě MyMethod se zadaným plně kvalifikovaným podpisem.
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) Odpovídá konkrétním metodám MyMethod1 a MyMethod2 příslušným plně kvalifikovaným podpisům.

Vyloučení konkrétních typů a jejich odvozených typů

Z analýzy můžete vyloučit konkrétní typy a jejich odvozené typy. Pokud chcete například určit, že pravidlo by se nemělo spouštět u žádné metody v rámci pojmenovaných MyType typů a jejich odvozených typů, přidejte do souboru .editorconfig v projektu následující dvojici klíč-hodnota:

dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType

Povolené formáty názvů symbolů v hodnotě možnosti (oddělené ):|

  • Pouze název typu (zahrnuje všechny typy s názvem bez ohledu na typ nebo obor názvů).
  • Plně kvalifikované názvy ve formátu ID dokumentace symbolu s volitelnou T: předponou.

Příklady:

Hodnota možnosti Shrnutí
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType Odpovídá všem pojmenovaným MyType typům a všem jejich odvozeným typům.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 Odpovídá všem typům pojmenovaným buď MyType1 nebo MyType2 a všem jejich odvozeným typům.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType Odpovídá určitému typu MyType s daným plně kvalifikovaným názvem a všemi jeho odvozenými typy.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 Odpovídá konkrétním typům MyType1 a MyType2 příslušným plně kvalifikovaným názvům a všem jejich odvozeným typům.

Příklady pseudokódu

Porušení

using Newtonsoft.Json;

public class BookRecord
{
    public string Title { get; set; }
    public object Location { get; set; }
}

public abstract class Location
{
    public string StoreId { get; set; }
}

public class AisleLocation : Location
{
    public char Aisle { get; set; }
    public byte Shelf { get; set; }
}

public class WarehouseLocation : Location
{
    public string Bay { get; set; }
    public byte Shelf { get; set; }
}

public class ExampleClass
{
    public BookRecord DeserializeBookRecord(JsonReader reader)
    {
        JsonSerializer jsonSerializer = new JsonSerializer();
        jsonSerializer.TypeNameHandling = TypeNameHandling.Auto;
        return jsonSerializer.Deserialize<BookRecord>(reader);    // CA2329 violation
    }
}
Imports Newtonsoft.Json

Public Class BookRecord
    Public Property Title As String
    Public Property Location As Location
End Class

Public MustInherit Class Location
    Public Property StoreId As String
End Class

Public Class AisleLocation
    Inherits Location

    Public Property Aisle As Char
    Public Property Shelf As Byte
End Class

Public Class WarehouseLocation
    Inherits Location

    Public Property Bay As String
    Public Property Shelf As Byte
End Class

Public Class ExampleClass
    Public Function DeserializeBookRecord(reader As JsonReader) As BookRecord
        Dim jsonSerializer As JsonSerializer = New JsonSerializer()
        jsonSerializer.TypeNameHandling = TypeNameHandling.Auto
        Return JsonSerializer.Deserialize(Of BookRecord)(reader)    ' CA2329 violation
    End Function
End Class

Řešení

using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

public class BookRecordSerializationBinder : ISerializationBinder
{
    // To maintain backwards compatibility with serialized data before using an ISerializationBinder.
    private static readonly DefaultSerializationBinder Binder = new DefaultSerializationBinder();

    public void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        Binder.BindToName(serializedType, out assemblyName, out typeName);
    }

    public Type BindToType(string assemblyName, string typeName)
    {
        // If the type isn't expected, then stop deserialization.
        if (typeName != "BookRecord" && typeName != "AisleLocation" && typeName != "WarehouseLocation")
        {
            return null;
        }

        return Binder.BindToType(assemblyName, typeName);
    }
}

public class BookRecord
{
    public string Title { get; set; }
    public object Location { get; set; }
}

public abstract class Location
{
    public string StoreId { get; set; }
}

public class AisleLocation : Location
{
    public char Aisle { get; set; }
    public byte Shelf { get; set; }
}

public class WarehouseLocation : Location
{
    public string Bay { get; set; }
    public byte Shelf { get; set; }
}

public class ExampleClass
{
    public BookRecord DeserializeBookRecord(JsonReader reader)
    {
        JsonSerializer jsonSerializer = new JsonSerializer();
        jsonSerializer.TypeNameHandling = TypeNameHandling.Auto;
        jsonSerializer.SerializationBinder = new BookRecordSerializationBinder();
        return jsonSerializer.Deserialize<BookRecord>(reader);
    }
}
Imports System
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Serialization

Public Class BookRecordSerializationBinder
    Implements ISerializationBinder

    ' To maintain backwards compatibility with serialized data before using an ISerializationBinder.
    Private Shared ReadOnly Property Binder As New DefaultSerializationBinder()

    Public Sub BindToName(serializedType As Type, ByRef assemblyName As String, ByRef typeName As String) Implements ISerializationBinder.BindToName
        Binder.BindToName(serializedType, assemblyName, typeName)
    End Sub

    Public Function BindToType(assemblyName As String, typeName As String) As Type Implements ISerializationBinder.BindToType
        ' If the type isn't expected, then stop deserialization.
        If typeName <> "BookRecord" AndAlso typeName <> "AisleLocation" AndAlso typeName <> "WarehouseLocation" Then
            Return Nothing
        End If

        Return Binder.BindToType(assemblyName, typeName)
    End Function
End Class

Public Class BookRecord
    Public Property Title As String
    Public Property Location As Location
End Class

Public MustInherit Class Location
    Public Property StoreId As String
End Class

Public Class AisleLocation
    Inherits Location

    Public Property Aisle As Char
    Public Property Shelf As Byte
End Class

Public Class WarehouseLocation
    Inherits Location

    Public Property Bay As String
    Public Property Shelf As Byte
End Class

Public Class ExampleClass
    Public Function DeserializeBookRecord(reader As JsonReader) As BookRecord
        Dim jsonSerializer As JsonSerializer = New JsonSerializer()
        jsonSerializer.TypeNameHandling = TypeNameHandling.Auto
        jsonSerializer.SerializationBinder = New BookRecordSerializationBinder()
        Return jsonSerializer.Deserialize(Of BookRecord)(reader)
    End Function
End Class

CA2326: Nepoužívejte jiné hodnoty TypeNameHandling než None

CA2327: Nepoužívejte nezabezpečený JsonSerializer Nastavení

CA2328: Ujistěte se, že je zabezpečený jsonSerializer Nastavení

CA2330: Ujistěte se, že má jsonSerializer při deserializaci zabezpečenou konfiguraci.