SSL Certificate Analysis Open Port Detection Web Application Scanning DNS Security Audit HTTP Header Analysis Misconfiguration Detection Software Fingerprinting Subdomain Enumeration
SSL Certificate Analysis Open Port Detection Web Application Scanning DNS Security Audit HTTP Header Analysis Misconfiguration Detection Software Fingerprinting Subdomain Enumeration

All Entries

Category Insecure Deserialization / Data Integrity
Typical Severity Critical
OWASP A08:2021 – Software and Data Integrity Failures
CWE CWE-502: Deserialization of Untrusted Data
Also known as Object Injection, Unsafe Deserialization, Serialization Vulnerability
Affected systems Java, PHP, Python, Ruby, .NET web applications; APIs accepting serialized objects; caching layers; message queues
Common formats Java serialized streams, PHP serialize(), Python pickle, .NET BinaryFormatter, YAML, XML (XStream), JSON (with type hints)

Overview

Serialization is the process of converting an in-memory object into a byte stream or structured text so it can be stored or transmitted. Deserialization is the reverse: reconstructing an object from that representation. Insecure deserialization arises when an application deserializes data supplied or influenced by an attacker without verifying its integrity or constraining the permitted object types.

Because deserialization can trigger constructor calls, property setters, and magic methods during object reconstruction, an attacker who controls the serialized payload can often redirect execution through existing code ("gadget chains") to achieve outcomes far beyond what the application intended — most severely, arbitrary remote code execution (RCE) on the server.

How it works

The attack surface depends heavily on the runtime and serialization format, but the general mechanism is consistent:

  1. Attacker-controlled serialized data enters the application — via cookies, POST bodies, HTTP headers, API payloads, message queues, or shared caches.
  2. The application deserializes without validation — it reconstructs objects without checking a cryptographic signature, restricting allowed classes, or sanitizing field values.
  3. Gadget chains are triggered — the attacker crafts a payload whose object graph passes through classes already loaded in the JVM/CLR/interpreter that, in combination, execute attacker-supplied commands. Tools like ysoserial (Java), phpggc (PHP), and pwnlib (Python) automate gadget-chain discovery and payload generation.
  4. Impact materialises — depending on the gadget chain available, the outcome may be RCE, arbitrary file read/write, SSRF, denial of service, or authentication bypass.

Language-specific notes:

  • Java: ObjectInputStream.readObject() is the classic entry point. Dozens of gadget chains exist in common libraries (Apache Commons Collections, Spring Framework, etc.).
  • PHP: unserialize() triggers __wakeup(), __destruct(), and __toString() magic methods on attacker-controlled classes.
  • Python: pickle.loads() executes arbitrary Python via the __reduce__ protocol; this is a design-level risk, not just an implementation flaw.
  • .NET: BinaryFormatter, NetDataContractSerializer, and TypeNameHandling in Newtonsoft.Json with type-name resolution enabled are well-known attack surfaces; Microsoft has deprecated BinaryFormatter in .NET 5+.
  • YAML/XML: Parsers that resolve type tags (PyYAML yaml.load(), XStream) can instantiate arbitrary classes.

Business impact

Successful exploitation can yield complete server compromise. Specific consequences include:

  • Remote code execution: Attackers gain OS-level access, enabling data exfiltration, ransomware deployment, or use of the server as a pivot point.
  • Authentication and authorisation bypass: Tampered session objects or role fields can grant administrative privileges without valid credentials.
  • Data integrity violation: Attackers may modify in-flight business objects (e.g., prices, quantities, user IDs) before they are persisted.
  • Denial of service: Deeply nested or circular object graphs can exhaust heap memory or CPU during reconstruction.
  • Regulatory exposure: Server compromise typically triggers breach notification obligations under GDPR, HIPAA, PCI DSS, and similar frameworks, with associated fines and reputational damage.

How to fix it

  1. Avoid deserializing untrusted data entirely — prefer data-only formats (plain JSON without type hints, Protocol Buffers, MessagePack) that cannot instantiate arbitrary objects.
  2. Implement integrity verification — sign serialized payloads with an HMAC or digital signature and verify the signature before deserialization. Reject payloads whose signatures do not match.
  3. Apply strict allowlisting of deserializable types — in Java, wrap ObjectInputStream with a custom resolveClass() that rejects any class not on an explicit whitelist (e.g., using Apache Commons IO's ValidatingObjectInputStream or the JEP 290 serial filter mechanism). In .NET, use TypeNameHandling.None in Newtonsoft.Json and avoid BinaryFormatter.
  4. Upgrade or replace deprecated serializers — migrate away from BinaryFormatter (.NET), pickle for untrusted data (Python), and yaml.load() without a safe loader (use yaml.safe_load()).
  5. Run deserialization in a sandboxed context — confine the deserializing process to a low-privilege account, container, or OS-level sandbox (seccomp, AppArmor) to limit the blast radius of a successful exploit.
  6. Keep dependencies current — gadget chains often rely on vulnerable versions of third-party libraries. Regularly audit and update dependencies using SCA tooling.
  7. Log and monitor deserialization events — alert on unexpected class instantiation, unusually large payloads, or deserialization errors, which may indicate active probing.
  8. Conduct security testing — include deserialization attack payloads in penetration tests and use tools such as ysoserial or phpggc in controlled environments to verify exposure. Sensagraph automatically detects insecure deserialization indicators in web applications.

References

Frequently asked questions

Serialization converts an in-memory object into a storable or transmittable format (e.g., a byte stream or JSON string). Deserialization is the reverse process — reconstructing the original object from that representation. The security risk lies in deserialization, because the act of reconstructing an object can execute code (constructors, magic methods) that an attacker may be able to direct.

Python's pickle protocol allows serialized data to embed arbitrary Python opcodes via the __reduce__ method. When pickle.loads() processes a malicious payload, it can execute any Python expression on the host system. This is a fundamental design property of the format, not just an implementation bug, which is why pickle should never be used to deserialize data from untrusted sources.

A gadget chain is a sequence of existing classes and methods already present in the application's classpath or library set that, when chained together during deserialization, produce a dangerous side effect — typically remote code execution. Attackers craft serialized payloads that route execution through these classes without introducing any new code themselves.

Plain JSON (without type metadata or polymorphic type handling) is generally safe because it represents data, not objects with executable logic. However, JSON libraries configured with type-name resolution — such as Newtonsoft.Json with TypeNameHandling set to Auto or All, or Jackson with default typing enabled — reintroduce the same object-instantiation risks as binary serialization formats.

Detection approaches include static analysis (identifying calls to dangerous deserializers such as ObjectInputStream.readObject(), unserialize(), or pickle.loads() that process external input), dynamic testing with crafted payloads (e.g., ysoserial for Java, phpggc for PHP), and runtime instrumentation that monitors class instantiation during deserialization. Automated scanners such as Sensagraph can identify surface-level indicators of this vulnerability in web applications.

It is predominantly a server-side risk, but client-side JavaScript environments can also be affected if they deserialize data using eval(), JSON.parse() with custom reviver functions, or library-specific formats that instantiate objects with executable behaviour. The highest-severity scenarios — particularly remote code execution — occur on the server.