Solutions

Cyber Security – Replacing BinaryFormatter in .NET

Cyber Security – BinaryFormatter: A Security Risk

The .NET source code is constantly evolving, and its development team pays close attention to cyber security issues. However, legacy classes such as BinaryFormatter still have vulnerabilities that attackers can exploit. In this analysis, we discuss the critical vulnerability associated with BinaryFormatter, tracked under CVE-2023-32737, CWE-502, and CA2300 (you can read more at the links), explaining what these issues are, how they affect security, and the best practices to mitigate them.

What is BinaryFormatter?

BinaryFormatter is a .NET Framework class used to serialize and deserialize objects in binary format, making it easier to store or transfer complex data. However, because of the way BinaryFormatter handles data during deserialization, it can be susceptible to insecure deserialization attacks, where malicious input can execute arbitrary code and compromise the application’s security.

Cyber Security – Understanding the Vulnerability Codes

CVE-2023-32737: Common Vulnerabilities and Exposures

CVE-2023-32737 is a specific identifier for an “insecure deserialization” vulnerability found in BinaryFormatter. It indicates that tampering with serialized data makes it possible to exploit the class, allowing code to perform unexpected and potentially malicious actions in the application’s runtime environment.

CWE-502: Weakness Category

CWE-502 refers to the “Deserialization of Untrusted Data” category. This classification indicates that a vulnerability occurs when malicious data is deserialized, which can trigger unwanted code execution. In other words, processing potentially dangerous input data can threaten the system’s security and compromise its integrity.

CA2300: Code Analysis for Security

CA2300 recommends avoiding the direct processing of untrusted data, ensuring greater system security. This warning alerts developers during the build process, flagging insecure practices such as directly deserializing data from unknown sources.

Impact of the BinaryFormatter Vulnerability

When using BinaryFormatter, applications run the risk of receiving malicious binary objects that can execute unwanted code during deserialization. This vulnerability is a serious threat because it allows privilege escalation or remote command execution, compromising the integrity of the system.

Because it is a widely used library included in the .NET Framework (not to be confused with .NET Core, where using BinaryFormatter is already discouraged and has limited support), many systems can be potential targets, especially those that interact with data from external sources.

Cyber Security – Four ways to mitigate the BinaryFormatter problem

1. Replace BinaryFormatter

  • Microsoft already recommends avoiding BinaryFormatter in new projects, encouraging the use of safer alternatives such as System.Text.Json, XmlSerializer, or DataContractSerializer.

2. Verify the Data Source

  • Make sure serialized data comes from trusted sources. Even when using alternative serialization methods, it is important to control and ensure the reliability of the data source.

3. Cyber Security – Update .NET and Apply Security Patches

  • Microsoft regularly releases updates and patches to fix vulnerabilities. Make sure your development environment and applications are running the latest versions of the .NET Framework.

4. Run Static Code Analysis

  • Static analysis tools such as Code Analysis for .NET (which provides the CA2300 warning) can detect the use of BinaryFormatter and suggest changes before the application is deployed.

Safe Alternatives for Serialization

As a best practice, developers can consider using secure serializers suited to the specific data and scenarios at hand. Some of the recommended alternatives include:

  • System.Text.Json: A lightweight and secure alternative for JSON serialization.
  • DataContractSerializer: Suited to service-to-service communication scenarios, as it offers more control over what gets serialized.
  • Protobuf: A highly efficient and secure alternative, especially for communication between microservices.
  • NrbfDecoder: An alternative for reading and interpreting binary objects that stays compatible with BinaryFormatter. It decodes the NRBF format (.NET Remoting Binary Format), letting you work with binary data without the code-execution risks present in BinaryFormatter. Although it is not a drop-in replacement, NrbfDecoder can help you migrate legacy data or analyze binaries safely. Learn more about NrbfDecoder on the Microsoft website.

Cyber Security – Replacing BinaryFormatter with NrbfDecoder

Imagine a scenario where we receive data through an API that was formatted with BinaryFormatter. In other words, we have no control over the client, only over the API, which also deserializes this data with BinaryFormatter.

This case is a security problem because malicious code may arrive within that data. How can we fix our side without breaking the contract with the consumers of our APIs?

One option is to use NrbfDecoder, a library available on NuGet. At the time of writing, it is still a Release Candidate, although Microsoft already considers it “production-ready”. This is because its API is still expected to go through a major update.

Below, let’s explore a deserialization solution using the NrbfDecoder mentioned earlier.

Assume the class below was serialized with BinaryFormatter and that we receive a MemoryStream containing this class.

public class Employee
{
 public int Id { get; set; }
 public List<string> Roles { get; set; }
}

Now for the deserialization code:

...
// Check whether the MemoryStream can be deserialized
if (NrbfDecoder.StartsWithPayloadHeader(memoryStream))
{
 memoryStream.Position = 0;
 // Decode the instance of a class that is not an array or a primitive type
 ClassRecord decodedClass = NrbfDecoder.DecodeClassRecord(memoryStream);

 // Iterate over the members to bind them by name
 foreach (var memberName in decodedClass.MemberNames)
 {
  if (memberName.Equals(nameof(employee.Id))
  {
   // Handling primitive types
   employee.Id = decodedClass.GetInt32(memberName);
  }

  if (memberName.Equals(nameof(employee.Roles))
  {
   var complexDecoded = decodedClass.GetClassRecord(memberName);

   // Identify the type so it can be handled correctly
   if (complexDecoded.TypeName.FullName.Contains("List[[System.String]]"))
   {
    var listDecoded = complexDecoded.GetArrayRecord("_items")
                    .GetArray(expectedArrayType: typeof(string));

    foreach (var item in listDecoded)
    {
     // If it is a primitive type
     if (item is not ClassRecord)
     {
      employee.Roles.Add(item);
     }

     // If it is not a primitive type, keep decoding the
     // classes or arrays the same way we did earlier.
    }
   }
  }
 }

 // In the end, we have a deserialized instance of the Employee class

Conclusion

Although BinaryFormatter is a powerful tool in .NET, it has become a source of risk because of its susceptibility to insecure deserialization. The vulnerability identified as CVE-2023-32737 and categorized under CWE-502 highlights the need to adopt safe serialization and data-handling practices. That is why Microsoft and the .NET community recommend replacing BinaryFormatter with safer serialization methods, protecting applications and preventing exploits from compromising system integrity.

Vinicius Sodré

Formado em Ciência da Computação pela Unicarioca, desenvolvedor de software com 15 anos de experiência em grandes empresas nacionais e multinacionais. Vinicius está à frente deste blog, feito de desenvolvedor para desenvolvedores de iniciantes a experientes.

Compartilhar
Publicado por:
Vinicius Sodré

Posts Recentes

Python Web Frameworks: A Complete Guide

Web development has evolved significantly in recent years, and Python frameworks are at the forefront…

1 year atrás

Python for AI: Master the Path to Artificial Intelligence

Artificial intelligence is revolutionizing every sector of society, from enterprise applications to everyday solutions. At…

1 year atrás

Tuples and Sets in Python: When to Use Each One – Lesson 11

In this lesson of the Python mini course, I want to cover two collection types…

1 year atrás

Dictionaries in Python: Everything You Need to Know – Lesson 10

Among Python's most versatile data structures, dictionaries stand out. They help us represent structured data…

2 years atrás

Lists in Python: Everything You Need to Know – Lesson 9

In this ninth lesson of the mini course, I want to talk about one of…

2 years atrás

Variable Scope in Python: Understand It and Get Rid of Bugs – Lesson 8

Understanding variable scope in Python is essential to avoid errors and write more predictable programs.…

2 years atrás

Este blog utiliza cookies. Se você continuar assumiremos que você está satisfeito com ele.

Leia Mais...