CA2322. Убедитесь, что JavaScriptSerializer не был инициализирован с помощью SimpleTypeResolver до десериализацииCA2322: Ensure JavaScriptSerializer is not initialized with SimpleTypeResolver before deserializing

ЗначениеValue
Идентификатор правилаRule ID CA2322CA2322
КатегорияCategory БезопасностьSecurity
Исправление не критическое или не критическоеFix is breaking or non-breaking Не критическоеNon-breaking

ПричинаCause

System.Web.Script.Serialization.JavaScriptSerializerМетод десериализации был вызван или указан, и JavaScriptSerializer может быть инициализирован с помощью System.Web.Script.Serialization.SimpleTypeResolver .A System.Web.Script.Serialization.JavaScriptSerializer deserialization method was called or referenced and the JavaScriptSerializer may have been initialized with a System.Web.Script.Serialization.SimpleTypeResolver.

По умолчанию это правило анализирует всю базу кода, но это можно настроить.By default, this rule analyzes the entire codebase, but this is configurable.

Описание правилаRule description

Небезопасные десериализаторы уязвимы при десериализации ненадежных данных.Insecure deserializers are vulnerable when deserializing untrusted data. Злоумышленник может изменить сериализованные данные, чтобы включить непредвиденные типы для внедрения объектов с вредоносными побочными эффектами.An attacker could modify the serialized data to include unexpected types to inject objects with malicious side effects. Атака в небезопасном десериализаторе может, например, выполнять команды в базовой операционной системе, взаимодействовать по сети или удалять файлы.An attack against an insecure deserializer could, for example, execute commands on the underlying operating system, communicate over the network, or delete files.

Это правило находит System.Web.Script.Serialization.JavaScriptSerializer вызовы метода десериализации или ссылки, когда JavaScriptSerializer может быть инициализировано с помощью System.Web.Script.Serialization.SimpleTypeResolver .This rule finds System.Web.Script.Serialization.JavaScriptSerializer deserialization method calls or references, when the JavaScriptSerializer may have been initialized with a System.Web.Script.Serialization.SimpleTypeResolver.

Устранение нарушенийHow to fix violations

  • Убедитесь, что JavaScriptTypeResolver объекты не инициализированы с помощью System.Web.Script.Serialization.SimpleTypeResolver .Ensure JavaScriptTypeResolver objects aren't initialized with a System.Web.Script.Serialization.SimpleTypeResolver.
  • Если код должен считывать данные, сериализованные с помощью SimpleTypeResolver , ограничьте десериализованные типы до ожидаемого списка, реализовав пользовательскую JavaScriptTypeResolver .If your code needs to read data serialized using a SimpleTypeResolver, restrict deserialized types to an expected list by implementing a custom JavaScriptTypeResolver.
  • Сделайте сериализованные данные несанкционированными.Make the serialized data tamper-proof. После сериализации криптографически подписывает сериализованные данные.After serialization, cryptographically sign the serialized data. Перед десериализациюм проверьте криптографическую подпись.Before deserialization, validate the cryptographic signature. Защитите криптографический ключ от раскрывать и разрабатывать для смены ключей.Protect the cryptographic key from being disclosed and design for key rotations.

Когда следует подавлять предупрежденияWhen to suppress warnings

Предупреждение из этого правила можно отключить, если:It's safe to suppress a warning from this rule if:

  • Известно, что входные данные являются доверенными.You know the input is trusted. Учтите, что границы доверия и потоки данных приложения могут меняться со временем.Consider that your application's trust boundary and data flows may change over time.
  • Вы предоставили одно из предосторожностей по устранению нарушений.You've taken one of the precautions in How to fix violations.

Настройка анализируемого кодаConfigure code to analyze

Используйте следующие параметры, чтобы настроить, на какие части базы кода следует запускать это правило.Use the following options to configure which parts of your codebase to run this rule on.

Эти параметры можно настроить только для этого правила, для всех правил или для всех правил в этой категории (Безопасность).You can configure these options for just this rule, for all rules, or for all rules in this category (Security). Дополнительные сведения см. в разделе Параметры конфигурации правила качества кода.For more information, see Code quality rule configuration options.

Исключить конкретные символыExclude specific symbols

Вы можете исключить из анализа определенные символы, например типы и методы.You can exclude specific symbols, such as types and methods, from analysis. Например, чтобы указать, что правило не должно выполняться в каком-либо коде в типах с именем MyType , добавьте следующую пару "ключ-значение" в editorconfig -файл в проекте:For example, to specify that the rule should not run on any code within types named MyType, add the following key-value pair to an .editorconfig file in your project:

dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType

Допустимые форматы имен символов в значении параметра (разделенные | ):Allowed symbol name formats in the option value (separated by |):

  • Только имя символа (включает все символы с именем, независимо от содержащего его типа или пространства имен).Symbol name only (includes all symbols with the name, regardless of the containing type or namespace).
  • Полные имена в формате идентификатора документациисимвола.Fully qualified names in the symbol's documentation ID format. Для каждого имени символа требуется префикс типа символа, например M: для методов, T: для типов и N: для пространств имен.Each symbol name requires a symbol-kind prefix, such as M: for methods, T: for types, and N: for namespaces.
  • .ctor для конструкторов и .cctor для статических конструкторов..ctor for constructors and .cctor for static constructors.

Примеры:Examples:

Значение параметраOption Value СводкаSummary
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType Соответствует всем символам с именем MyType .Matches all symbols named MyType.
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 Соответствует всем символам с именем MyType1 или MyType2 .Matches all symbols named either MyType1 or MyType2.
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) Соответствует конкретному методу MyMethod с указанной полной сигнатурой.Matches specific method MyMethod with the specified fully qualified signature.
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) Соответствует конкретным методам MyMethod1 и MyMethod2 соответствующим полным сигнатурам.Matches specific methods MyMethod1 and MyMethod2 with the respective fully qualified signatures.

Исключить определенные типы и их производные типыExclude specific types and their derived types

Из анализа можно исключить определенные типы и их производные типы.You can exclude specific types and their derived types from analysis. Например, чтобы указать, что правило не должно выполняться для каких-либо методов в типах с именем MyType и производных типов, добавьте следующую пару "ключ-значение" в editorconfig -файл в проекте:For example, to specify that the rule should not run on any methods within types named MyType and their derived types, add the following key-value pair to an .editorconfig file in your project:

dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType

Допустимые форматы имен символов в значении параметра (разделенные | ):Allowed symbol name formats in the option value (separated by |):

  • Только имя типа (включает все типы с именем, независимо от содержащего его типа или пространства имен).Type name only (includes all types with the name, regardless of the containing type or namespace).
  • Полные имена в формате идентификатора документациисимвола с дополнительным T: префиксом.Fully qualified names in the symbol's documentation ID format, with an optional T: prefix.

Примеры:Examples:

Значение параметраOption Value ИтогиSummary
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType Соответствует всем типам с именем MyType и всем их производным типам.Matches all types named MyType and all of their derived types.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 Соответствует всем типам с именами MyType1 или MyType2 и всем производным от него типам.Matches all types named either MyType1 or MyType2 and all of their derived types.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType Соответствует определенному типу MyType с заданным полным именем и всеми производными от него типами.Matches specific type MyType with given fully qualified name and all of its derived types.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 Соответствует конкретным типам MyType1 и MyType2 с соответствующими полными именами и всем их производным типам.Matches specific types MyType1 and MyType2 with the respective fully qualified names, and all of their derived types.

Примеры псевдо-кодаPseudo-code examples

Нарушение 1Violation 1

using System.Web.Script.Serialization;

public class ExampleClass
{
    public JavaScriptSerializer Serializer { get; set; }

    public T Deserialize<T>(string str)
    {
        return this.Serializer.Deserialize<T>(str);
    }
}
Imports System.Web.Script.Serialization

Public Class ExampleClass
    Public Property Serializer As JavaScriptSerializer

    Public Function Deserialize(Of T)(str As String) As T
        Return Me.Serializer.Deserialize(Of T)(str)
    End Function
End Class

Решение 1Solution 1

using System.Web.Script.Serialization;

public class ExampleClass
{
    public T Deserialize<T>(string str)
    {
        JavaScriptSerializer s = new JavaScriptSerializer();
        return s.Deserialize<T>(str);
    }
}
Imports System.Web.Script.Serialization

Public Class ExampleClass
    Public Function Deserialize(Of T)(str As String) As T
        Dim s As JavaScriptSerializer = New JavaScriptSerializer()
        Return s.Deserialize(Of T)(str)
    End Function
End Class

Нарушение 2Violation 2

using System.Web.Script.Serialization;

public class BookRecord
{
    public string Title { get; set; }
    public string Author { get; set; }
    public int PageCount { get; set; }
    public AisleLocation Location { get; set; }
}

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

public class ExampleClass
{
    public JavaScriptSerializer Serializer { get; set; }

    public BookRecord DeserializeBookRecord(string s)
    {
        return this.Serializer.Deserialize<BookRecord>(s);
    }
}
Imports System.Web.Script.Serialization

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

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

Public Class ExampleClass
    Public Property Serializer As JavaScriptSerializer

    Public Function DeserializeBookRecord(str As String) As BookRecord
        Return Me.Serializer.Deserialize(Of BookRecord)(str)
    End Function
End Class

Решение 2Solution 2

using System;
using System.Web.Script.Serialization;

public class BookRecordTypeResolver : JavaScriptTypeResolver
{
    // For compatibility with data serialized with a JavaScriptSerializer initialized with SimpleTypeResolver.
    private static readonly SimpleTypeResolver Simple = new SimpleTypeResolver();

    public override Type ResolveType(string id)
    {
        // One way to discover expected types is through testing deserialization
        // of **valid** data and logging the types used.

        ////Console.WriteLine($"ResolveType('{id}')");

        if (id == typeof(BookRecord).AssemblyQualifiedName || id == typeof(AisleLocation).AssemblyQualifiedName)
        {
            return Simple.ResolveType(id);
        }
        else
        {
            throw new ArgumentException("Unexpected type ID", nameof(id));
        }
    }

    public override string ResolveTypeId(Type type)
    {
        return Simple.ResolveTypeId(type);
    }
}

public class BookRecord
{
    public string Title { get; set; }
    public string Author { get; set; }
    public int PageCount { get; set; }
    public AisleLocation Location { get; set; }
}

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

public class ExampleClass
{
    public BookRecord DeserializeBookRecord(string s)
    {
        JavaScriptSerializer serializer = new JavaScriptSerializer(new BookRecordTypeResolver());
        return serializer.Deserialize<BookRecord>(s);
    }
}
Imports System
Imports System.Web.Script.Serialization

Public Class BookRecordTypeResolver
    Inherits JavaScriptTypeResolver

    ' For compatibility with data serialized with a JavaScriptSerializer initialized with SimpleTypeResolver.
    Private Dim Simple As SimpleTypeResolver = New SimpleTypeResolver()

    Public Overrides Function ResolveType(id As String) As Type
        ' One way to discover expected types is through testing deserialization
        ' of **valid** data and logging the types used.

        ''Console.WriteLine($"ResolveType('{id}')")

        If id = GetType(BookRecord).AssemblyQualifiedName Or id = GetType(AisleLocation).AssemblyQualifiedName Then
            Return Simple.ResolveType(id)
        Else
            Throw New ArgumentException("Unexpected type", NameOf(id))
        End If
    End Function

    Public Overrides Function ResolveTypeId(type As Type) As String
        Return Simple.ResolveTypeId(type)
    End Function
End Class

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

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

Public Class ExampleClass
    Public Function DeserializeBookRecord(str As String) As BookRecord
        Dim serializer As JavaScriptSerializer = New JavaScriptSerializer(New BookRecordTypeResolver())
        Return serializer.Deserialize(Of BookRecord)(str)
    End Function
End Class

CA2321. Не десериализируйте с помощью JavaScriptSerializer, используя SimpleTypeResolverCA2321: Do not deserialize with JavaScriptSerializer using a SimpleTypeResolver