Insecure Deserialization
Insecure Deserialization is a critical vulnerability that occurs when untrusted data is used to reconstruct objects in an application. It can lead to remote code execution, privilege escalation, and complete system compromise, making it one of the most dangerous web application security risks.
What Is Insecure Deserialization?
Insecure Deserialization is a vulnerability that arises when an application deserializes (reconstructs) objects from untrusted data sources without proper validation or sanitization. Serialization is the process of converting an object into a format that can be stored or transmitted (such as JSON, XML, or binary), while deserialization reverses this process to recreate the object. When attackers can manipulate serialized data before it is deserialized, they can inject malicious objects that execute arbitrary code or alter application logic.
This vulnerability was identified as A08 in the 2017 OWASP Top 10 as "Insecure Deserialization" due to its severe impact and increasing prevalence. In the 2021 OWASP Top 10, it was merged into the broader category A08: Software and Data Integrity Failures, which encompasses deserialization vulnerabilities along with other integrity-related issues such as insecure CI/CD pipelines and unsigned code execution. Despite this categorization change, insecure deserialization remains a critical threat that can lead to complete system takeover.
The danger of insecure deserialization lies in the fact that serialized data often contains not just simple values, but complex object graphs with code references, class definitions, and method invocations. When an attacker controls this data, they can craft malicious payloads that exploit the deserialization process itself. Many programming languages and frameworks provide native serialization mechanisms that, by design, can instantiate arbitrary classes and invoke methods during deserialization, creating a powerful attack surface if not properly secured.
How It Works
The attacker discovers an application endpoint that accepts serialized data, such as a session cookie, API parameter, or file upload. They analyze the data format to determine the serialization mechanism being used (Java serialization, Python pickle, PHP serialize, etc.).
Using knowledge of available classes in the application or its dependencies, the attacker constructs a "gadget chain"—a sequence of method calls that, when triggered during deserialization, execute malicious code. For example, in Java, attackers might leverage classes from Apache Commons Collections to build a payload that executes system commands.
The attacker transmits the crafted serialized object to the vulnerable endpoint. This could be through modifying a session cookie, sending a POST request with serialized data, or uploading a malicious file that will be deserialized by the server.
The application receives the serialized data and deserializes it without performing integrity checks, type validation, or allowlist filtering. The deserialization process automatically instantiates objects and invokes methods defined in the serialized data, treating the untrusted input as legitimate.
As the deserialization process reconstructs the malicious object graph, the gadget chain triggers, executing the attacker's payload. This can result in remote code execution, allowing the attacker to run arbitrary commands on the server, access sensitive data, or completely compromise the system.
Vulnerable Code Example
@RestController
public class UserPreferencesController {
@PostMapping("/preferences/load")
public ResponseEntity<?> loadPreferences(@RequestBody byte[] data) {
try {
// VULNERABLE: Deserializing untrusted data
// without any validation or filtering
ByteArrayInputStream bis = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bis);
// This will execute any code embedded in the
// serialized object during deserialization
UserPreferences prefs = (UserPreferences) ois.readObject();
return ResponseEntity.ok(prefs);
} catch (Exception e) {
return ResponseEntity.status(500).body("Error loading preferences");
}
}
}
// An attacker can craft a malicious serialized object using
// gadget chains from libraries like Apache Commons Collections.
// When deserialized, this object executes arbitrary commands:
//
// ysoserial CommonsCollections1 "rm -rf /tmp/*" | base64
//
// The resulting payload, when sent to /preferences/load,
// will execute the command during deserialization.Secure Code Example
@RestController
public class UserPreferencesController {
private final ObjectMapper objectMapper = new ObjectMapper();
@PostMapping("/preferences/load")
public ResponseEntity<?> loadPreferences(@RequestBody String jsonData) {
try {
// SECURE: Use JSON instead of Java serialization
// JSON only supports data types, not arbitrary code
UserPreferences prefs = objectMapper.readValue(
jsonData, UserPreferences.class
);
return ResponseEntity.ok(prefs);
} catch (Exception e) {
return ResponseEntity.status(400).body("Invalid preferences format");
}
}
// If you MUST use Java serialization, implement strict allowlisting:
public Object secureDeserialize(byte[] data) throws Exception {
ByteArrayInputStream bis = new ByteArrayInputStream(data);
// Use ObjectInputFilter to allowlist only safe classes
ObjectInputStream ois = new ObjectInputStream(bis);
ois.setObjectInputFilter(info -> {
if (info.serialClass() != null) {
String className = info.serialClass().getName();
// Only allow specific, safe classes
if (className.equals("com.example.UserPreferences")) {
return ObjectInputFilter.Status.ALLOWED;
}
return ObjectInputFilter.Status.REJECTED;
}
return ObjectInputFilter.Status.UNDECIDED;
});
return ois.readObject();
}
}
// Using JSON eliminates gadget chain attacks entirely.
// If native serialization is required, ObjectInputFilter
// restricts deserialization to explicitly allowed classes.Types of Insecure Deserialization
Remote Code Execution (RCE)
The most severe form of insecure deserialization, where attackers exploit gadget chains to execute arbitrary code on the server. Gadget chains are sequences of existing classes (often from popular libraries like Apache Commons Collections, Spring Framework, or Groovy) that can be chained together during deserialization to trigger method invocations leading to command execution. Tools like ysoserial automate the creation of these payloads, making exploitation accessible even to less sophisticated attackers.
Data Tampering
Attackers modify serialized objects to alter application state or business logic. For example, an attacker might deserialize a shopping cart object, change the price field from $100 to $1, then reserialize and send it back. Similarly, serialized session objects containing user roles can be modified to escalate privileges from a regular user to an administrator. This type of attack is common when applications store serialized objects in cookies, hidden form fields, or local storage without integrity protection.
Denial of Service (DoS)
Malicious serialized objects can be designed to consume excessive server resources during deserialization. Attackers can create deeply nested object graphs or recursive structures that cause the deserialization process to consume all available memory or CPU. For example, a "HashSet collision" attack creates a HashSet with many objects that hash to the same value, causing O(n²) time complexity during deserialization. These attacks can crash application servers or make them unresponsive.
Impact
Insecure Deserialization vulnerabilities can have catastrophic consequences, often leading to complete system compromise. The impact severity is typically rated as critical due to the potential for remote code execution.
Attackers can execute arbitrary code on the server, install backdoors, create new user accounts, or pivot to other systems on the internal network. Once code execution is achieved, the attacker has the same privileges as the application process, potentially leading to complete server compromise.
By manipulating serialized session objects or user role data, attackers can elevate their privileges from a low-privilege user to an administrator. This allows them to access administrative functions, modify system configurations, and gain access to sensitive data that should be restricted.
Once an attacker gains code execution or elevated privileges, they can access and exfiltrate sensitive data including customer information, financial records, trade secrets, and proprietary code. The breach may go undetected for extended periods, allowing attackers to establish persistent access.
Denial of service attacks through malicious deserialization can crash application servers, consume all available resources, or trigger cascading failures across distributed systems. This can result in significant downtime, revenue loss, and damage to brand reputation.
Prevention Checklist
The most effective prevention is to avoid deserializing untrusted data altogether. Use data-only formats like JSON, XML, or Protocol Buffers that do not support arbitrary code execution during deserialization. These formats only represent data structures and cannot instantiate arbitrary classes or invoke methods.
If you must use native serialization, implement filters that explicitly allowlist the classes that can be deserialized. In Java, use ObjectInputFilter; in .NET, use SerializationBinder. Reject any class that is not on the allowlist. Never use denylists—attackers can always find new gadget chains to bypass them.
If serialized data must be transmitted to clients and back, protect its integrity using digital signatures or HMAC. Sign the serialized data before sending it and verify the signature before deserializing. This prevents attackers from tampering with the data. Use authenticated encryption (e.g., AES-GCM) for additional confidentiality.
Isolate deserialization operations in sandboxed environments or containers with minimal privileges. If an exploit succeeds, the attacker's access should be limited to the sandboxed environment, preventing lateral movement or system-wide compromise. Use principle of least privilege for all application processes.
Implement comprehensive logging for all deserialization operations, especially those involving external data. Monitor for anomalies such as unexpected class types, large object graphs, or deserialization failures. Set up alerts for suspicious patterns that may indicate exploitation attempts.
Regularly update all third-party libraries and frameworks, as many deserialization vulnerabilities arise from gadget chains in popular libraries. Use tools like OWASP Dependency-Check or Snyk to identify vulnerable dependencies. Consider removing or replacing libraries that are known sources of gadget chains (e.g., Apache Commons Collections 3.x).
Real-World Examples
Apache Struts 2 (Equifax Breach)
The Equifax data breach, one of the most significant in history, was enabled by an insecure deserialization vulnerability in Apache Struts 2 (CVE-2017-5638). Attackers exploited this vulnerability to gain remote code execution, ultimately compromising personal data of 147 million people. The breach cost Equifax over $1.4 billion in settlements and remediation costs.
Jenkins CI Server
Multiple insecure deserialization vulnerabilities were discovered in Jenkins, a widely-used continuous integration server. The vulnerabilities allowed unauthenticated attackers to execute arbitrary code on Jenkins servers by sending malicious serialized Java objects to the CLI interface or through the remoting protocol. Organizations running exposed Jenkins instances were at risk of complete server compromise.
Oracle WebLogic Server
Oracle WebLogic Server suffered from critical deserialization vulnerabilities (CVE-2019-2725, CVE-2019-2729) that allowed remote, unauthenticated attackers to execute arbitrary code. Attackers actively exploited these vulnerabilities in the wild to deploy cryptocurrency miners and ransomware on vulnerable servers. The vulnerabilities affected thousands of internet-facing WebLogic installations.
Apache Commons Collections
Security researcher Chris Frohoff discovered that Apache Commons Collections library could be used to create gadget chains for remote code execution through Java deserialization. This finding led to the discovery that countless Java applications using this popular library were vulnerable to RCE attacks. The research fundamentally changed how the security community viewed deserialization and led to widespread code remediation efforts.
Ready to Test Your Knowledge?
Put what you have learned into practice. Try identifying and fixing Insecure Deserialization vulnerabilities in our interactive coding challenges, or explore more security guides to deepen your understanding.