title | description | ms.date | author | ms.author | dev_langs | f1_keywords | ||||
---|---|---|---|---|---|---|---|---|---|---|
CA2301: Do not call BinaryFormatter.Deserialize without first setting BinaryFormatter.Binder (code analysis) |
Learn about code analysis rule CA2301: Do not call BinaryFormatter.Deserialize without first setting BinaryFormatter.Binder |
07/15/2020 |
dotpaul |
paulming |
|
|
Property | Value |
---|---|
Rule ID | CA2301 |
Title | Do not call BinaryFormatter.Deserialize without first setting BinaryFormatter.Binder |
Category | Security |
Fix is breaking or non-breaking | Non-breaking |
Enabled by default in .NET 9 | No |
A xref:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter?displayProperty=nameWithType deserialization method was called or referenced without the xref:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.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.Formatters.Binary.BinaryFormatter?displayProperty=nameWithType deserialization method calls or references, when xref:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter doesn't have its xref:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Binder set. If you want to disallow any deserialization with xref:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter regardless of the xref:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Binder property, disable this rule and CA2302, and enable rule CA2300.
[!INCLUDEfix-binaryformatter-serializationbinder]
BinaryFormatter
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 they apply to, or for all rules in this category (Security) that they apply 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.Formatters.Binary;
[Serializable]
public class BookRecord
{
public string Title { get; set; }
public AisleLocation Location { get; set; }
}
[Serializable]
public class AisleLocation
{
public char Aisle { get; set; }
public byte Shelf { get; set; }
}
public class ExampleClass
{
public BookRecord DeserializeBookRecord(byte[] bytes)
{
BinaryFormatter formatter = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream(bytes))
{
return (BookRecord) formatter.Deserialize(ms);
}
}
}
Imports System
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
<Serializable()>
Public Class BookRecord
Public Property Title As String
Public Property Location As AisleLocation
End Class
<Serializable()>
Public Class AisleLocation
Public Property Aisle As Char
Public Property Shelf As Byte
End Class
Public Class ExampleClass
Public Function DeserializeBookRecord(bytes As Byte()) As BookRecord
Dim formatter As BinaryFormatter = New BinaryFormatter()
Using ms As MemoryStream = New MemoryStream(bytes)
Return CType(formatter.Deserialize(ms), BookRecord)
End Using
End Function
End Class
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
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));
}
}
}
[Serializable]
public class BookRecord
{
public string Title { get; set; }
public AisleLocation Location { get; set; }
}
[Serializable]
public class AisleLocation
{
public char Aisle { get; set; }
public byte Shelf { get; set; }
}
public class ExampleClass
{
public BookRecord DeserializeBookRecord(byte[] bytes)
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Binder = new BookRecordSerializationBinder();
using (MemoryStream ms = new MemoryStream(bytes))
{
return (BookRecord) formatter.Deserialize(ms);
}
}
}
Imports System
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
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
<Serializable()>
Public Class BookRecord
Public Property Title As String
Public Property Location As AisleLocation
End Class
<Serializable()>
Public Class AisleLocation
Public Property Aisle As Char
Public Property Shelf As Byte
End Class
Public Class ExampleClass
Public Function DeserializeBookRecord(bytes As Byte()) As BookRecord
Dim formatter As BinaryFormatter = New BinaryFormatter()
formatter.Binder = New BookRecordSerializationBinder()
Using ms As MemoryStream = New MemoryStream(bytes)
Return CType(formatter.Deserialize(ms), BookRecord)
End Using
End Function
End Class
CA2300: Do not use insecure deserializer BinaryFormatter
CA2302: Ensure BinaryFormatter.Binder is set before calling BinaryFormatter.Deserialize