Insecure deserialization to remote code execution
An application that deserializes attacker-controlled data without validation can be driven to instantiate objects that execute code during deserialization — turning a serialized blob in a cookie, parameter or upload into a shell on the server.
Scenario
An authorized web-application assessment. You notice the app accepts serialized objects (a Java/.NET/PHP/Python blob in a cookie, hidden field or API body). The objective is to show whether that input is deserialized unsafely and what it leads to.
- 1
Discovery
Identify a deserialization sink
Spot serialized data by its markers (Java's rO0 / 0xACED, .NET BinaryFormatter, PHP's O:, Python pickle) in cookies, parameters, caches or uploads, and map which input reaches a deserializer — the sink is what makes this exploitable, so confirm it before anything else.
DetectionUnusual serialized payloads in requests, and deserialization errors in application logs, are early signals.
MitigationPrefer data-only formats (JSON) with a schema; never deserialize untrusted input with a format that can instantiate arbitrary types.
- 2
Credential Access / Discovery
Understand the target's gadgets
Determine the libraries on the classpath/dependencies, because exploitation relies on existing 'gadget' chains in those libraries. Where readable, review configuration and dependency manifests to see which known chains could apply, documenting the reasoning.
DetectionProbing for library versions and dependency endpoints, and failed gadget attempts, show in logs and WAF telemetry.
MitigationKeep dependencies patched and minimal, and remove libraries known to contain dangerous gadget chains.
- 3
Execution
Trigger code execution
Craft a serialized payload whose deserialization drives an available gadget chain to run a command, and send it through the identified input. Prove execution with a benign, logged marker (an out-of-band callback or a harmless command) rather than a destructive action.
DetectionA deserialization endpoint spawning a child process, and unexpected outbound callbacks, are high-value detections for EDR and egress monitoring.
MitigationRun the app with least privilege and no outbound egress it does not need, and add look-ahead deserialization filters (allow-lists) so unexpected types are rejected.
- 4
Persistence / Lateral Movement
Establish and demonstrate reach
Where in scope, show the impact of code execution — for example a minimal web shell or a staged tool — to map what the compromised app context can reach (secrets, internal services, the data store), then document everything for clean removal.
DetectionNew files in web-served directories, and tool transfers to the host, are strong post-exploitation signals.
MitigationMake web roots read-only, monitor file integrity, segment the app from internal services, and scope its credentials tightly.
Key takeaways
- Deserialization RCE needs a sink (untrusted input reaching a type-instantiating deserializer) and a gadget chain in the loaded libraries — both are required.
- Data-only formats with a schema remove the sink; type allow-lists and patched, minimal dependencies remove the gadgets.
- Least privilege and tight egress turn a successful deserialization into a contained incident rather than a pivot.