Skip to content

Latest commit

 

History

History
257 lines (202 loc) · 8.19 KB

File metadata and controls

257 lines (202 loc) · 8.19 KB
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
CSharp
VB
CA2311
DoNotDeserializeWithoutFirstSettingNetDataContractSerializerBinder

CA2311: Do not deserialize without first setting NetDataContractSerializer.Binder

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

Cause

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.

Rule description

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

How to fix violations

[!INCLUDEfix-binaryformatter-serializationbinder]

When to suppress warnings

NetDataContractSerializer 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;

[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

Solution

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

Related rules

CA2310: Do not use insecure deserializer NetDataContractSerializer

CA2312: Ensure NetDataContractSerializer.Binder is set before deserializing