Insecure deserialization - C-Sharp

Insecure deserialization - C-Sharp

Need

Secure deserialization process

Context

  • Usage of C# for developing robust and scalable applications
  • Usage of System for low-level operating system interactions and utilities
  • Usage of System.IO for input and output operations in .NET development
  • Usage of System.Runtime.Serialization.Formatters.Binary for binary serialization in .NET

Description

Non compliant code

        using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

public class Deserialization
{
    public void DeserializeObject(byte[] data)
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter();

        using (MemoryStream memoryStream = new MemoryStream(data))
        {
            object obj = binaryFormatter.Deserialize(memoryStream);
        }
    }
}
        
        

The above code is an example of insecure deserialization in a C# ASP.NET Core backend application. The DeserializeObject method takes a byte array as input and deserializes it into an object using the BinaryFormatter.Deserialize method.

This code is vulnerable because it does not validate the content of the serialized object before deserializing it. An attacker could manipulate the serialized data to include malicious code, which would then be executed when the object is deserialized.

Furthermore, the deserialized object is not cast to a specific type, which means that any object type can be deserialized. This increases the risk of executing unintended code or causing a system crash if the deserialized object type is not compatible with the expected object type.

To mitigate this vulnerability, it's recommended to validate and sanitize the serialized data before deserializing it, and to cast the deserialized object to a specific type. It's also a good practice to use safe deserialization methods that do not allow the execution of code during the deserialization process.

Steps

  • Implement input validation to ensure that only trusted and expected data is deserialized.
  • Use a whitelist approach to validate and restrict the types that can be deserialized.
  • Avoid deserializing untrusted or unknown data from untrusted sources.
  • Consider using a safer alternative to binary serialization, such as JSON or XML serialization with proper validation and type checking.
  • If binary serialization is necessary, consider using a secure serialization library that provides additional protection against deserialization vulnerabilities.
  • Regularly update and patch the libraries and frameworks used for serialization to benefit from security fixes and improvements.

Compliant code

        using System;
using System.IO;
using System.Runtime.Serialization;
using Newtonsoft.Json;

public class Deserialization
{
    public void DeserializeObject(byte[] data)
    {
        var settings = new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.None
        };

        using (MemoryStream memoryStream = new MemoryStream(data))
        {
            using (StreamReader reader = new StreamReader(memoryStream))
            {
                string jsonData = reader.ReadToEnd();
                object obj = JsonConvert.DeserializeObject(jsonData, settings);
            }
        }
    }
}
        
        

The updated code now uses JSON serialization instead of binary serialization, which is generally safer and less prone to deserialization vulnerabilities. The JsonSerializerSettings object is configured to not handle type names, which prevents arbitrary types from being deserialized. This is a form of whitelist validation, as only the types that are explicitly defined in the code will be deserialized.

The DeserializeObject method now reads the data from the MemoryStream into a string, which is then deserialized using JsonConvert.DeserializeObject. This method is safer than BinaryFormatter.Deserialize as it does not allow for the deserialization of arbitrary types.

This code still needs to be used carefully, as deserializing untrusted data can still lead to vulnerabilities. Always validate and sanitize input data before deserializing it, and avoid deserializing data from untrusted sources whenever possible.

Remember to regularly update and patch your serialization libraries to benefit from security fixes and improvements. In this case, ensure that you are using the latest version of Newtonsoft.Json.

References