Insecure Deserialization — Code Execution via Manipulated Objects
Insecure deserialization occurs when an application converts external data (JSON, XML, serialized bytes) back into objects without validating their integrity or origin. An attacker can manipulate the serialized stream to execute arbitrary code during the deserialization process.
Why It Is Dangerous
Languages like Java, PHP, and Python have native serialization mechanisms that allow saving and restoring full objects. When methods such as constructors, __wakeup (PHP), or readObject (Java) execute automatically upon deserialization, the attacker controls what runs.
Conceptual PHP Example
// Vulnerable class — runs a command in __wakeup
class Logger {
public $cmd;
public function __wakeup() {
// In a real system: NEVER run commands in magic methods
system($this->cmd);
}
}
// Serialized data received from the user (cookie, POST body)
$data = $_COOKIE['data'];
$obj = unserialize($data); // DANGER — triggers __wakeup with attacker-controlled cmd
An attacker can craft a serialized object with cmd = "id" to achieve remote code execution.
Java — Gadget Chains
In Java, the attack uses chains of classes already present in the classpath (“gadgets”) that, when deserialized, chain calls until code execution is reached.
// Common vector: base64-encoded serialized parameter via HTTP
POST /app/endpoint
Content-Type: application/x-java-serialized-object
rO0ABXNy... (base64-encoded Java serialized object, manipulated)
Tools like ysoserial (for use in authorized environments) generate test payloads for common libraries: Commons Collections, Spring, Hibernate.
Python — pickle
import pickle, os
class Exploit:
def __reduce__(self):
# Educational demonstration — in production NEVER use pickle with external data
return (os.system, ('echo pwned',))
data = pickle.dumps(Exploit())
pickle.loads(data) # executes os.system("echo pwned")
pickle is not safe for untrusted data. Use JSON or MessagePack for external data exchange.
Detection
Signs of insecure deserialization:
- Base64 parameters starting with "rO0" (Java) or "Tzo" (PHP)
- Cookies containing binary serialized data
- Endpoints accepting Content-Type: application/x-java-serialized-object
Prevention
1. Do not deserialize untrusted data using native formats.
Use JSON, Protobuf, or MessagePack — data formats without execution logic.
2. If native serialization is unavoidable, sign and verify before deserializing.
$hmac = hash_hmac('sha256', $serialized, SECRET_KEY);
// Verify HMAC before unserialize()
if (!hash_equals($expected_hmac, $received_hmac)) {
throw new Exception('Tampered data');
}
3. Java: use ObjectInputFilter to allowlist permitted classes.
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
"java.util.ArrayList;java.lang.String;!*"
);
ois.setObjectInputFilter(filter);
4. Monitor deserialization in production with RASP (Runtime Application Self-Protection) agents.
5. Keep dependencies updated — many gadget chains exploit old versions of popular libraries.