In the realm of cybersecurity, one vulnerability that continues to haunt developers and security professionals alike is insecure deserialization. This seemingly innocuous process, crucial for transferring data between systems, harbors a myriad of risks when implemented carelessly. We delve deep into the intricacies of insecure deserialization, uncover its potential threats. I will also demonstrate practical examples in PHP, Java, and Python.
What is serialization
Serialization is the process of converting complex data structures, such as objects and their fields, into a “flatter” format that can be sent and received as a sequential stream of bytes. Serializing data makes it much simpler to:
- Write complex data to inter-process memory, a file, or a database
- Send complex data, for example, over a network, between different components of an application, or in an API call
Crucially, when serializing an object, its state is also persisted. In other words, the object’s attributes are preserved, along with their assigned values.
Serialization vs deserialization

Deserialization is the process of reconstructing an object from its serialized form, typically used for transmitting data between different applications or storing objects in a persistent state. Serialized data is usually represented as a string of bytes, which can be easily transmitted over networks or stored in files.

What is Insecure Deserialization?
Insecure Deserialization occurs when data from an untrusted source is deserialized, and the application:
- Automatically instantiates classes and executes constructors/methods
- Does not validate the structure, type, or intent of deserialized objects
- Relies on unsafe deserialization libraries or insecure formats
This opens the door to attacks like:
- Remote Code Execution
- Privilege Escalation
- DoS (Denial of Service)
- Access Control Bypass
Real-World Example: RCE via Java Deserialization
Case: Apache Commons Collections (2015)
A critical vulnerability was discovered in the Apache Commons Collections library that allowed attackers to execute arbitrary code via serialized Java objects.
Attackers would send a malicious serialized object to a server endpoint that used ObjectInputStream
without validation. When deserialized, the object triggered a chain of method calls, ultimately running system commands.
๐งช Vulnerable Code Examples
๐ด Java (Insecure)
import java.io.*;
public class DeserializationExample {
public static void main(String[] args) throws Exception {
byte[] input = getRequestInput(); // from untrusted client
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(input));
Object obj = ois.readObject(); // ๐ฅ Dangerous!
System.out.println("Object: " + obj);
}
}
This code accepts input from an external source and blindly deserializes it using ObjectInputStream
. If the input is crafted, it can trigger unwanted behavior.
โ Java (Secure Approach)
import java.io.*;
import java.util.*;
public class SafeDeserialization {
public static void main(String[] args) throws Exception {
byte[] input = getRequestInput();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(input)) {
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
// Only allow specific classes to be deserialized
if (!desc.getName().equals("java.util.HashMap")) {
throw new InvalidClassException("Unauthorized deserialization attempt: " + desc.getName());
}
return super.resolveClass(desc);
}
};
Object obj = ois.readObject(); // Allowed: HashMap only
System.out.println("Safe object: " + obj);
}
}
๐ Fix: Limit the deserialized classes. Validate content. Use safe libraries.
๐ด Python (Vulnerable with pickle
)
import pickle
def deserialize_user_data(data):
obj = pickle.loads(data) # ๐ฅ Highly dangerous!
return obj
Python’s
pickle
can execute arbitrary code if the data is malicious.
โ Python (Secure alternative)
import json
def safe_deserialize(data):
obj = json.loads(data) # Safe for strings, dicts, lists
return obj
Use
json
or other non-executable formats for serialization whenever possible.
๐ด .NET C# (Insecure with BinaryFormatter)
We will discuss this in detail in our next blog post. But for basics, please refer below
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public object Deserialize(byte[] data)
{
BinaryFormatter formatter = new BinaryFormatter();
using MemoryStream stream = new MemoryStream(data);
return formatter.Deserialize(stream); // ๐ฅ Unsafe
}
โ .NET C# (Fix with Json or DataContract)
using System.Text.Json;
public T DeserializeSafe<T>(string json)
{
return JsonSerializer.Deserialize<T>(json); // โ
Safe
}
Microsoft recommends never using BinaryFormatter and switching to safer alternatives like
System.Text.Json
.
๐ก๏ธ Defense-in-Depth: How to Prevent Insecure Deserialization
Practice | Why It Helps |
---|---|
Never deserialize untrusted input | Core rule. Always sanitize external data. |
Use safe formats (JSON, XML) | No method calls during deserialization. |
Whitelist allowed types | Prevent instantiation of dangerous classes. |
Use application firewalls (WAF) | Block known exploit signatures. |
Apply strict input validation | Ensure only expected data is processed. |
Update deserialization libraries | Vulnerabilities in older libs are common. |
Monitor logs for anomaly patterns | Detect unexpected object structures. |
๐งฐ Tools and Libraries That Help
- ๐ OWASP Dependency Check โ Identify vulnerable components
- ๐ง SerialKiller (Java) โ Safe whitelist-based deserialization
- ๐ Static analysis tools (e.g., SonarQube, Fortify) โ Spot deserialization issues in code
- ๐ง WAF (Web Application Firewall) โ Block serialized payload attacks
โ Golden Rule: Never trust serialized input from external sources. If you must deserialize, sanitize ruthlessly.
Please use for portswigger labs learning the exploits.
Pingback: Insecure Deserialization in .NET: Risk and Fixing Legacy Code - iosec.in