CA2311: Nie deserializuj bez pierwszego ustawienia NetDataContractSerializer.Binder
Właściwości | Wartość |
---|---|
Identyfikator reguły | CA2311 |
Tytuł | Nie wykonuj deserializacji bez uprzedniego ustawienia właściwości NetDataContractSerializer.Binder |
Kategoria | Bezpieczeństwo |
Poprawka powodująca niezgodność lub niezgodność | Niezgodność |
Domyślnie włączone na platformie .NET 9 | Nie. |
Przyczyna
Metoda System.Runtime.Serialization.NetDataContractSerializer deserializacji została wywołana lub odwołana bez Binder zestawu właściwości.
Domyślnie ta reguła analizuje całą bazę kodu, ale można to skonfigurować.
Ostrzeżenie
Ograniczanie typów za pomocą klasy SerializationBinder nie może zapobiec wszystkim atakom. Aby uzyskać więcej informacji, zobacz Przewodnik po zabezpieczeniach BinaryFormatter.
Opis reguły
Niezabezpieczone deserializatory są podatne na deserializacji niezaufanych danych. Osoba atakująca może zmodyfikować serializowane dane w celu uwzględnienia nieoczekiwanych typów w celu wstrzyknięcia obiektów ze złośliwymi skutkami ubocznymi. Atak na niezabezpieczonego deserializatora może na przykład wykonywać polecenia w bazowym systemie operacyjnym, komunikować się za pośrednictwem sieci lub usuwać pliki.
Ta reguła znajduje System.Runtime.Serialization.NetDataContractSerializer wywołania metody deserializacji lub odwołania, gdy NetDataContractSerializer nie ma jego Binder zestawu. Jeśli chcesz uniemożliwić deserializacji NetDataContractSerializer niezależnie od Binder właściwości, wyłącz tę regułę i CA2312 i włącz regułę CA2310.
Jak naprawić naruszenia
- Zamiast tego użyj bezpiecznego serializatora i nie zezwalaj osobie atakującej na określenie dowolnego typu do deserializacji. Aby uzyskać więcej informacji, zobacz Preferowane alternatywy.
- Ustaw serializacji danych na dowód manipulacji. Po serializacji kryptograficznie podpisz serializowane dane. Przed deserializacji zweryfikuj podpis kryptograficzny. Ochrona klucza kryptograficznego przed ujawnieniem i projektowaniem rotacji kluczy.
- Ta opcja sprawia, że kod jest podatny na ataki typu "odmowa usługi" i możliwe ataki zdalnego wykonywania kodu w przyszłości. Aby uzyskać więcej informacji, zobacz Przewodnik po zabezpieczeniach BinaryFormatter. Ogranicz deserializowane typy. Zaimplementuj niestandardowy System.Runtime.Serialization.SerializationBinderelement . Przed deserializacji ustaw
Binder
właściwość na wystąpienie niestandardowe SerializationBinder we wszystkich ścieżkach kodu. W metodzie przesłoniętej BindToType , jeśli typ jest nieoczekiwany, należy zgłosić wyjątek, aby zatrzymać deserializacji.
Kiedy pomijać ostrzeżenia
NetDataContractSerializer
jest niezabezpieczony i nie można go zabezpieczyć.
Konfigurowanie kodu do analizowania
Użyj poniższych opcji, aby skonfigurować, które części bazy kodu mają być uruchamiane w tej regule.
Możesz skonfigurować te opcje tylko dla tej reguły, dla wszystkich reguł, do których ma ona zastosowanie, lub dla wszystkich reguł w tej kategorii (Zabezpieczenia), których dotyczy. Aby uzyskać więcej informacji, zobacz Opcje konfiguracji reguły jakości kodu.
Wykluczanie określonych symboli
Z analizy można wykluczyć określone symbole, takie jak typy i metody. Aby na przykład określić, że reguła nie powinna być uruchamiana w żadnym kodzie w typach o nazwie MyType
, dodaj następującą parę klucz-wartość do pliku editorconfig w projekcie:
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType
Dozwolone formaty nazw symboli w wartości opcji (oddzielone przez |
):
- Tylko nazwa symbolu (zawiera wszystkie symbole o nazwie, niezależnie od typu zawierającego lub przestrzeni nazw).
- W pełni kwalifikowane nazwy w formacie identyfikatora dokumentacji symbolu. Każda nazwa symboli wymaga prefiksu typu symboli, takiego jak
M:
metody,T:
dla typów iN:
przestrzeni nazw. .ctor
dla konstruktorów i.cctor
konstruktorów statycznych.
Przykłady:
Wartość opcji | Podsumowanie |
---|---|
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType |
Pasuje do wszystkich symboli o nazwie MyType . |
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 |
Pasuje do wszystkich symboli o nazwie MyType1 lub MyType2 . |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) |
Pasuje do określonej metody MyMethod z określonym w pełni kwalifikowanym podpisem. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) |
Pasuje do określonych metod MyMethod1 i MyMethod2 z odpowiednimi w pełni kwalifikowanymi podpisami. |
Wykluczanie określonych typów i ich typów pochodnych
Z analizy można wykluczyć określone typy i ich typy pochodne. Aby na przykład określić, że reguła nie powinna być uruchamiana na żadnych metodach w typach nazwanych MyType
i ich typach pochodnych, dodaj następującą parę klucz-wartość do pliku .editorconfig w projekcie:
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType
Dozwolone formaty nazw symboli w wartości opcji (oddzielone przez |
):
- Nazwa typu (zawiera tylko wszystkie typy o nazwie, niezależnie od typu zawierającego lub przestrzeni nazw).
- W pełni kwalifikowane nazwy w formacie identyfikatora dokumentacji symbolu z opcjonalnym
T:
prefiksem.
Przykłady:
Wartość opcji | Podsumowanie |
---|---|
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType |
Pasuje do wszystkich typów nazwanych MyType i wszystkich ich typów pochodnych. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 |
Dopasuje wszystkie typy o nazwie MyType1 lub MyType2 i wszystkie ich typy pochodne. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType |
Pasuje do określonego typu MyType z daną w pełni kwalifikowaną nazwą i wszystkimi jego typami pochodnymi. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 |
Pasuje do określonych typów MyType1 i MyType2 z odpowiednimi w pełni kwalifikowanymi nazwami i wszystkimi ich typami pochodnymi. |
Przykłady przykładów kodu przykładowego
Naruszenie
using System;
using System.IO;
using System.Runtime.Serialization;
[DataContract]
public class BookRecord
{
[DataMember]
public string Title { get; set; }
[DataMember]
public AisleLocation Location { get; set; }
}
[DataContract]
public class AisleLocation
{
[DataMember]
public char Aisle { get; set; }
[DataMember]
public byte Shelf { get; set; }
}
public class ExampleClass
{
public BookRecord DeserializeBookRecord(byte[] bytes)
{
NetDataContractSerializer serializer = new NetDataContractSerializer();
using (MemoryStream ms = new MemoryStream(bytes))
{
return (BookRecord) serializer.Deserialize(ms); // CA2311 violation
}
}
}
Imports System
Imports System.IO
Imports System.Runtime.Serialization
<DataContract()>
Public Class BookRecord
<DataMember()>
Public Property Title As String
<DataMember()>
Public Property Location As AisleLocation
End Class
<DataContract()>
Public Class AisleLocation
<DataMember()>
Public Property Aisle As Char
<DataMember()>
Public Property Shelf As Byte
End Class
Public Class ExampleClass
Public Function DeserializeBookRecord(bytes As Byte()) As BookRecord
Dim serializer As NetDataContractSerializer = New NetDataContractSerializer()
Using ms As MemoryStream = New MemoryStream(bytes)
Return CType(serializer.Deserialize(ms), BookRecord) ' CA2311 violation
End Using
End Function
End Class
Rozwiązanie
using System;
using System.IO;
using System.Runtime.Serialization;
public class BookRecordSerializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
// One way to discover expected types is through testing deserialization
// of **valid** data and logging the types used.
////Console.WriteLine($"BindToType('{assemblyName}', '{typeName}')");
if (typeName == "BookRecord")
{
return typeof(BookRecord);
}
else if (typeName == "AisleLocation")
{
return typeof(AisleLocation);
}
else
{
throw new ArgumentException("Unexpected type", nameof(typeName));
}
}
}
[DataContract]
public class BookRecord
{
[DataMember]
public string Title { get; set; }
[DataMember]
public AisleLocation Location { get; set; }
}
[DataContract]
public class AisleLocation
{
[DataMember]
public char Aisle { get; set; }
[DataMember]
public byte Shelf { get; set; }
}
public class ExampleClass
{
public BookRecord DeserializeBookRecord(byte[] bytes)
{
NetDataContractSerializer serializer = new NetDataContractSerializer();
serializer.Binder = new BookRecordSerializationBinder();
using (MemoryStream ms = new MemoryStream(bytes))
{
return (BookRecord) serializer.Deserialize(ms);
}
}
}
Imports System
Imports System.IO
Imports System.Runtime.Serialization
Public Class BookRecordSerializationBinder
Inherits SerializationBinder
Public Overrides Function BindToType(assemblyName As String, typeName As String) As Type
' One way to discover expected types is through testing deserialization
' of **valid** data and logging the types used.
'Console.WriteLine($"BindToType('{assemblyName}', '{typeName}')")
If typeName = "BinaryFormatterVB.BookRecord" Then
Return GetType(BookRecord)
Else If typeName = "BinaryFormatterVB.AisleLocation" Then
Return GetType(AisleLocation)
Else
Throw New ArgumentException("Unexpected type", NameOf(typeName))
End If
End Function
End Class
<DataContract()>
Public Class BookRecord
<DataMember()>
Public Property Title As String
<DataMember()>
Public Property Location As AisleLocation
End Class
<DataContract()>
Public Class AisleLocation
<DataMember()>
Public Property Aisle As Char
<DataMember()>
Public Property Shelf As Byte
End Class
Public Class ExampleClass
Public Function DeserializeBookRecord(bytes As Byte()) As BookRecord
Dim serializer As NetDataContractSerializer = New NetDataContractSerializer()
serializer.Binder = New BookRecordSerializationBinder()
Using ms As MemoryStream = New MemoryStream(bytes)
Return CType(serializer.Deserialize(ms), BookRecord)
End Using
End Function
End Class
Powiązane reguły
CA2310: Nie używaj niezabezpieczonego deserializatora NetDataContractSerializer