Imagine you could send someone a package that, when opened, automatically runs any program you want on their computer. That's essentially what insecure deserialization allows - except the "package" is serialized data, and the "program" is arbitrary code execution on the server.
Serialization converts objects into a format that can be stored or transmitted (like JSON, XML, or binary). Deserialization does the reverse - it reconstructs objects from that data. The problem? If an application deserializes untrusted data, attackers can craft malicious objects that execute code when reconstructed.
Insecure deserialization is #8 on the OWASP Top 10 and often leads directly to Remote Code Execution. It's been responsible for major breaches including the 2017 Equifax hack.
Serialization 101
Before we break it, let's understand it. Serialization is how applications save complex data structures:
13606070;"># Pickle is DESIGNED to execute code during deserialization
14606070;"># The __reduce__ method can return arbitrary functions to call
Look for these identifiers in cookies, POST data, or headers: • Java: Base64 starting with rO0AB or hex AC ED 00 05 • PHP: Strings like O:4:"User" or a:2:{s:4: • Python Pickle: Base64 binary blobs in cookies
Why Deserialization = RCE
The magic happens because many languages allow objects to have special methods that run automatically during deserialization:
14606070;"># If response takes 10 seconds, it worked!
Not all applications have vulnerable libraries. ysoserial only works if the target has the corresponding library (Commons Collections, Spring, etc.) in its classpath.
Tool: PHPGGC (PHP Generic Gadget Chains) is like ysoserial but for PHP. It generates payloads for popular frameworks like Laravel, Symfony, WordPress, etc.
Python Pickle Attacks
Pickle is Dangerous by Design
python
1import pickle
2import os
3
4606070;"># Pickle allows defining HOW to reconstruct objects
5606070;"># The __reduce__ method returns a function + args to call
6
7class Evil:
8def __reduce__(self):
9606070;"># When unpickled, this calls os.system("id")
A web application stores user preferences in a cookie:
Cookie: prefs=Tzo0OiJVc2VyIjoyOntzOjQ6Im5hbWUiO3M6NToiYWRtaW4iO3M6NDoicm9sZSI7czo0OiJ1c2VyIjt9
After base64 decoding:
O:4:"User":2:{s:4:"name";s:5:"admin";s:4:"role";s:4:"user";}
You find that the application has a LogWriter class:
class LogWriter {
public $logFile;
public $logData;
function __destruct() {
file_put_contents($this->logFile, $this->logData);
}
}
Write a webshell to /var/www/html/shell.php
Need a hint? (4 available)
Java Blind RCE
Challenge
🔥 medium
A Java application has an API endpoint:
POST /api/import
Content-Type: application/octet-stream
[binary data]
You notice the binary data starts with 0xACED (Java serialization magic).
The server returns only {"status": "processed"} regardless of input.
You have no direct output, but you control a server at attacker.com.
Prove RCE exists and execute commands.
Need a hint? (4 available)
Python Cookie Pickle
Challenge
🔥 medium
A Flask application uses this code for session handling:
@app.route('/dashboard')
def dashboard():
user_data = request.cookies.get('session')
if user_data:
user = pickle.loads(base64.b64decode(user_data))
return f"Welcome {user.name}!"
return "Not logged in"
You're logged in and your cookie is:
session=gASVGwAAAAAAAACMBF9fbWFpbl9flIwEVXNlcpSTlCmBlH0=
Achieve command execution.
Need a hint? (4 available)
Knowledge Check
Deserialization Quiz
Question 1 of 5
What makes deserialization vulnerabilities so dangerous?
Key Takeaways
Deserialization = potential RCE in Java, PHP, Python, Ruby, and .NET applications
Magic methods (readObject, __destruct, __reduce__) execute automatically during deserialization
Gadget chains link existing classes to achieve code execution
Detection: Look for rO0AB (Java), O: (PHP), or binary blobs in cookies/parameters