CA2330: Asegurarse de que la configuración de JsonSerializer es segura al deserializar
Propiedad | Value |
---|---|
Identificador de la regla | CA2330 |
Título | Asegurarse de que la configuración de JsonSerializer es segura al deserializar |
Categoría | Seguridad |
La corrección interrumpe o no interrumpe | Poco problemático |
Habilitado de forma predeterminada en .NET 9 | No |
Causa
Esta regla se activa cuando ambas de las siguientes condiciones podrían ser ciertas para una instancia Newtonsoft.Json.JsonSerializer que se ha pasado a un método de deserialización o se ha inicializado como un campo o una propiedad:
- La propiedad TypeNameHandling es un valor distinto de
None
. - La propiedad SerializationBinder es NULL.
Esta regla es similar a la regla CA2329, pero en este caso, el análisis no puede determinar definitivamente si el serializador está configurado de forma no segura.
De forma predeterminada, esta regla analiza todo el código base, pero es configurable.
Descripción de la regla
Los deserializadores no seguros son vulnerables al deserializar datos que no son de confianza. Un atacante podría modificar los datos serializados para incluir tipos inesperados a fin de insertar objetos con efectos secundarios malintencionados. Un ataque contra un deserializador inseguro podría, por ejemplo, ejecutar comandos en el sistema operativo subyacente, comunicarse a través de la red o eliminar archivos.
Esta regla busca instancias Newtonsoft.Json.JsonSerializer que puedan haberse configurado para deserializar tipos especificados en la entrada, pero que pueden no haberse configurado para restringir los tipos deserializados con un Newtonsoft.Json.Serialization.ISerializationBinder. Si quiere impedir la deserialización de los tipos especificados en la entrada por completo, deshabilite las reglas CA2327, CA2328, CA2329 y CA2330, y habilite la regla CA2326 en su lugar.
Cómo corregir infracciones
- Si es posible, use el valor
None
de TypeNameHandling. - Proteja los datos serializados contra alteraciones. Después de la serialización, firme criptográficamente los datos serializados. Antes de la deserialización, valide la firma criptográfica. Proteja la clave criptográfica para que no se revele y diseñe las rotaciones de clave.
- Restrinja los tipos deserializados. Implemente un Newtonsoft.Json.Serialization.ISerializationBinder personalizado. Antes de deserializar con Json.NET, asegúrese de que el ISerializationBinder personalizado se ha especificado en la propiedad Newtonsoft.Json.JsDeserialize. SerializationBinder. En el método Newtonsoft.Json.Serialization.ISerializationBinder.BindToType, si el tipo es inesperado, devuelva
null
o produzca una excepción para detener la deserialización.
Cuándo suprimir las advertencias
Se puede suprimir una advertencia de esta regla si:
- Sabe que la entrada es de confianza. Considera que el límite de confianza de la aplicación y los flujos de datos pueden cambiar con el tiempo.
- Ha tomado una de las precauciones indicadas en Cómo corregir infracciones.
- Sabe que la propiedad Newtonsoft.Json.Jsbiserializer.SerializationBinder siempre se establece cuando la propiedad TypeNameHandling es un valor distinto de
None
.
Supresión de una advertencia
Si solo quiere suprimir una única infracción, agregue directivas de preprocesador al archivo de origen para deshabilitar y volver a habilitar la regla.
#pragma warning disable CA2330
// The code that's violating the rule is on this line.
#pragma warning restore CA2330
Para deshabilitar la regla de un archivo, una carpeta o un proyecto, establezca su gravedad en none
del archivo de configuración.
[*.{cs,vb}]
dotnet_diagnostic.CA2330.severity = none
Para obtener más información, consulte Procedimiento para suprimir advertencias de análisis de código.
Configuración del código para analizar
Use las opciones siguientes para configurar en qué partes del código base se va a ejecutar esta regla.
Puede configurar estas opciones solo para esta regla, para todas las reglas a las que se aplica o para todas las reglas de esta categoría (Seguridad) a las que se aplica. Para más información, vea Opciones de configuración de reglas de calidad de código.
Exclusión de símbolos específicos
Puede excluir símbolos específicos, como tipos y métodos, del análisis. Por ejemplo, para especificar que la regla no se debe ejecutar en ningún código dentro de los tipos con el nombre MyType
, agregue el siguiente par clave-valor a un archivo .editorconfig en el proyecto:
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType
Formatos de nombre de símbolo permitidos en el valor de opción (separados por |
):
- Solo nombre de símbolo (incluye todos los símbolos con el nombre, con independencia del tipo contenedor o el espacio de nombres).
- Nombres completos en el formato de id. de documentación del símbolo. Cada nombre de símbolo necesita un prefijo de tipo símbolo, como
M:
para los métodos,T:
para los tipos yN:
para los espacios de nombres. .ctor
para los constructores y.cctor
para los constructores estáticos.
Ejemplos:
Valor de la opción | Resumen |
---|---|
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType |
Coincide con todos los símbolos denominados MyType . |
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 |
Coincide con todos los símbolos denominados MyType1 o MyType2 . |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) |
Coincide con un método MyMethod concreto con la signatura completa especificada. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) |
Coincide con los métodos MyMethod1 y MyMethod2 concretos con las signaturas completas especificadas. |
Exclusión de tipos específicos y sus tipos derivados
Puede excluir tipos específicos y sus tipos derivados del análisis. Por ejemplo, para especificar que la regla no se debe ejecutar en ningún método dentro de los tipos con el nombre MyType
y sus tipos derivados, agregue el siguiente par clave-valor a un archivo .editorconfig en el proyecto:
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType
Formatos de nombre de símbolo permitidos en el valor de opción (separados por |
):
- Solo nombre de tipo (incluye todos los tipos con el nombre, con independencia del tipo contenedor o el espacio de nombres).
- Nombres completos en el formato de identificador de documentación del símbolo, con un prefijo
T:
opcional.
Ejemplos:
Valor de la opción | Resumen |
---|---|
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType |
Coincide con todos los tipos denominados MyType y todos sus tipos derivados. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 |
Coincide con todos los tipos denominados MyType1 o MyType2 , y todos sus tipos derivados. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType |
Coincide con un tipo MyType específico con el nombre completo dado y todos sus tipos derivados. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 |
Coincide con los tipos MyType1 y MyType2 específicos con los correspondientes nombres completos y todos sus tipos derivados. |
Ejemplos de pseudocódigo
Infracción
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 static class Binders
{
public static ISerializationBinder BookRecord = new BookRecordSerializationBinder();
}
public class ExampleClass
{
public BookRecord DeserializeBookRecord(JsonReader reader)
{
JsonSerializer jsonSerializer = new JsonSerializer();
jsonSerializer.TypeNameHandling = TypeNameHandling.Auto;
jsonSerializer.SerializationBinder = Binders.BookRecord;
return jsonSerializer.Deserialize<BookRecord>(reader); // CA2330 -- SerializationBinder might be null
}
}
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 Binders
Public Shared Property BookRecord As ISerializationBinder = New BookRecordSerializationBinder()
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 = Binders.BookRecord
Return jsonSerializer.Deserialize(Of BookRecord)(reader) ' CA2330 -- SerializationBinder might be null
End Function
End Class
Solución
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 static class Binders
{
public static ISerializationBinder BookRecord = new BookRecordSerializationBinder();
}
public class ExampleClass
{
public BookRecord DeserializeBookRecord(JsonReader reader)
{
JsonSerializer jsonSerializer = new JsonSerializer();
jsonSerializer.TypeNameHandling = TypeNameHandling.Auto;
// Ensure that SerializationBinder is assigned non-null before deserializing
jsonSerializer.SerializationBinder = Binders.BookRecord ?? throw new Exception("Expected non-null");
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 Binders
Public Shared Property BookRecord As ISerializationBinder = New BookRecordSerializationBinder()
End Class
Public Class ExampleClass
Public Function DeserializeBookRecord(reader As JsonReader) As BookRecord
Dim jsonSerializer As JsonSerializer = New JsonSerializer()
jsonSerializer.TypeNameHandling = TypeNameHandling.Auto
' Ensure SerializationBinder is non-null before deserializing
jsonSerializer.SerializationBinder = If(Binders.BookRecord, New Exception("Expected non-null"))
Return jsonSerializer.Deserialize(Of BookRecord)(reader)
End Function
End Class
Reglas relacionadas
CA2326: No usar valores TypeNameHandling que no sean None
CA2327: No usar valores JsonSerializerSettings no seguros
CA2328: Asegurarse de que los valores JsonSerializerSettings sean seguros
CA2329: No deserializar con JsonSerializer y una configuración no segura