Skip to content

Latest commit

 

History

History
235 lines (188 loc) · 8.07 KB

File metadata and controls

235 lines (188 loc) · 8.07 KB
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
CSharp
VB
CA2301
DoNotCallBinaryFormatterDeserializeWithoutFirstSettingBinaryFormatterBinder

CA2301: Do not call BinaryFormatter.Deserialize without first setting BinaryFormatter.Binder

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 8 No

Cause

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.

Rule description

[!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.

How to fix violations

[!INCLUDEfix-binaryformatter-serializationbinder]

When to suppress warnings

BinaryFormatter is insecure and can't be made secure.

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 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]

Pseudo-code examples

Violation

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

Solution

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

Related rules

CA2300: Do not use insecure deserializer BinaryFormatter

CA2302: Ensure BinaryFormatter.Binder is set before calling BinaryFormatter.Deserialize