Insecure Deserialization

Insecure deserialization runs attacker-controlled object graphs, frequently leading to RCE through gadget chains.

Definition

Insecure deserialisation is the vulnerability that arises when an application takes a serialised byte stream from an untrusted source and reconstructs an object graph from it without verifying integrity or constraining the types it will instantiate. The byte stream embeds class names, field values, and — depending on the format — instructions to call methods during deserialisation. Reconstruction therefore touches code paths the attacker chose.

The infamous variants are Java's native serialisation, Python's binary object format, PHP's `unserialize`, Ruby's `Marshal`, and .NET's `BinaryFormatter`. All of them have a documented unsafe-by-default profile: rebuilding objects from attacker-controlled bytes is a known foot-gun, and security researchers have published "gadget chains" — sequences of widely-deployed library classes that, when materialised in a particular shape, produce arbitrary code execution.

How it works

Most exploitation walks through three stages. The attacker identifies an entry point where the application materialises untrusted bytes into objects (a session cookie, a JSON Web Token's nested JWT, a cache lookup, an inter-service RPC). The attacker then identifies a gadget chain — a path through the application's classpath that, when invoked through the deserialiser's machinery, performs a sensitive operation. Finally the attacker hand-builds a byte stream that triggers the gadget chain.

ysoserial (Java), ysoserial.net (.NET), and PHPGGC (PHP) automate the gadget-chain construction step for popular libraries. Once a target is identified as rebuilding untrusted bytes, building a working exploit is often hours, not weeks.

Impact

Almost universally RCE. Authentication bypass and information disclosure variants exist but the Java / .NET ecosystem has so many published gadget chains that a successful injection almost always becomes code execution.

Mitigation

Avoid materialising untrusted input. When you can't, use a format that doesn't include type information by default (JSON, Protocol Buffers, MessagePack) and validate the object schema after parsing. For Java, prefer `ObjectInputFilter` (JEP 290) with a strict allowlist. For .NET, abandon `BinaryFormatter` entirely — Microsoft has deprecated it. For Python, never feed untrusted bytes into the native binary loader; for PHP, never call `unserialize` on untrusted input. OWASP's Deserialization Cheat Sheet covers per-language remediations.

Examples

  • CVE-2021-44228 — Log4Shell composes JNDI lookup with deserialisation.
  • CVE-2017-5638 — Apache Struts OGNL evaluation rebuilds attacker input.

See also

References