Back to Technical Mode
Insecure Deserialization
Serialization formats that encode an object's class alongside its data (Java's native serialization, Python's pickle, PHP's unserialize) let an attacker specify which class gets instantiated. If any reachable class has a side-effecting constructor or method, that's a gadget for remote code execution.
The vulnerability isn't the data being wrong — it's the deserializer being willing to instantiate whatever class the payload names
"Gadget chains" string together otherwise-harmless classes already on the classpath/import path to reach a dangerous sink (like file write or process execution)
Signing serialized data doesn't help if the signing key is the same secret shipped in every install, or if the check happens after deserialization instead of before
The strongest fix is avoiding native object serialization for anything crossing a trust boundary — use a data-only format (JSON) with an explicit schema instead
Want this flow explained in detail as it plays?
POST/api/session/restore
Headers
Host:app.flowground.dev
Content-Type:application/x-java-serialized-object
Body
Loading...
Quick-Insert Payloads
Defense in depth
- Never deserialize untrusted input with a format that carries type/class information (native Java serialization, pickle, PHP unserialize, YAML with tags enabled) — use JSON with a strict schema instead
- If a legacy format truly can't be replaced, deserialize inside a sandboxed process with an allowlist of the only classes that are legitimately expected
- Treat serialized-object input from a client exactly like SQL or shell input: it is untrusted code, not untrusted data
Vulnerable vs. Fixed
import pickle
def restore_session(raw_bytes):
return pickle.loads(raw_bytes) # executes arbitrary code embedded in the payload