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.
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.
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 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 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.
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.
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:
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
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.
Web development has evolved significantly in recent years, and Python frameworks are at the forefront…
Artificial intelligence is revolutionizing every sector of society, from enterprise applications to everyday solutions. At…
In this lesson of the Python mini course, I want to cover two collection types…
Among Python's most versatile data structures, dictionaries stand out. They help us represent structured data…
In this ninth lesson of the mini course, I want to talk about one of…
Understanding variable scope in Python is essential to avoid errors and write more predictable programs.…
Este blog utiliza cookies. Se você continuar assumiremos que você está satisfeito com ele.
Leia Mais...