title | description | ms.date | author | ms.author | dev_langs | f1_keywords | ||||
---|---|---|---|---|---|---|---|---|---|---|
CA2311: Do not deserialize without first setting NetDataContractSerializer.Binder (code analysis) |
Learn about code analysis rule CA2311: Do not deserialize without first setting NetDataContractSerializer.Binder |
05/01/2019 |
dotpaul |
paulming |
|
|
Property | Value |
---|---|
Rule ID | CA2311 |
Title | Do not deserialize without first setting NetDataContractSerializer.Binder |
Category | Security |
Fix is breaking or non-breaking | Non-breaking |
Enabled by default in .NET 8 | No |
A xref:System.Runtime.Serialization.NetDataContractSerializer?displayProperty=nameWithType deserialization method was called or referenced without the xref:System.Runtime.Serialization.NetDataContractSerializer.Binder property set.
By default, this rule analyzes the entire codebase, but this is configurable.
Warning
Restricting types with a SerializationBinder can't prevent all attacks. For more information, see the BinaryFormatter security guide.
[!INCLUDEinsecure-deserializers-description]
This rule finds xref:System.Runtime.Serialization.NetDataContractSerializer?displayProperty=nameWithType deserialization method calls or references, when xref:System.Runtime.Serialization.NetDataContractSerializer doesn't have its xref:System.Runtime.Serialization.NetDataContractSerializer.Binder set. If you want to disallow any deserialization with xref:System.Runtime.Serialization.NetDataContractSerializer regardless of the xref:System.Runtime.Serialization.NetDataContractSerializer.Binder property, disable this rule and CA2312, and enable rule CA2310.
[!INCLUDEfix-binaryformatter-serializationbinder]
NetDataContractSerializer
is insecure and can't be made secure.
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 it applies to, or for all rules in this category (Security) that it applies to. For more information, see Code quality rule configuration options.
[!INCLUDEexcluded-symbol-names]
[!INCLUDEexcluded-type-names-with-derived-types]
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
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
CA2310: Do not use insecure deserializer NetDataContractSerializer
CA2312: Ensure NetDataContractSerializer.Binder is set before deserializing