Serialization turns an in-memory object into a byte stream; deserialization rebuilds it. The vulnerability is that most engines run engine-defined callbacks during reconstruction (magic methods, reducers, readback hooks), so a deserializer handed attacker-controlled bytes does not just produce data, it executes behavior. Chaining those callbacks across classes already loaded in the application reaches command execution, file writes, or SSRF. Impact is typically remote code execution.
The shared model#
Every language variant follows the same three-part pattern:
- A sink that deserializes untrusted input:
unserialize(),pickle.loads(),ObjectInputStream.readObject(),Marshal.load(),BinaryFormatter.Deserialize(),node-serialize.unserialize(). - A trigger: a callback the engine runs automatically on the rebuilt object (
__wakeup/__destruct,__reduce__,readObject,init_with, an IIFE), or a type the deserializer is told to instantiate. - A gadget chain: a sequence of methods on classes available in the target's codebase and dependencies that, once entered through the trigger, performs the attacker's action. The chain is assembled from whatever is on the classpath, which is why tools ship curated chains per framework.
Finding the sink#
- Recognize serialized formats on the wire: PHP
O:4:"User":..., Java base64 beginningrO0(hexAC ED 00 05), Python pickle opcodes, .NETAAEAAAD/////, Ruby Marshal\x04\x08. - Look in cookies, hidden fields,
Authorization/custom headers, caches, message queues, and import/upload features. - Confirm by tampering a byte and watching for a deserialization-specific error, then move to a controlled object.
Languages#
- PHP object injection:
unserialize(), magic-method POP chains, and reaching the sink without an explicit call viaphar://. - Python pickle:
__reduce__as a direct RCE primitive, plusyaml.loadand jsonpickle. - Java deserialization:
readObject, ysoserial gadget chains, and common entry points. - Ruby deserialization:
Marshal.loadandYAML.loaduniversal gadget chains. - .NET deserialization:
BinaryFormatter,TypeNameHandling, and ViewState. - Node.js deserialization:
node-serializeand function-revival libraries.
Tools#
- ysoserial (Java), ysoserial.net, PHPGGC (PHP gadget chains), marshalsec (Java/JVM)
References#
- PortSwigger Web Security Academy: Insecure deserialization
- OWASP: Deserialization Cheat Sheet