deserialization-insecure
Insecure deserialization playbook. Use when Java, PHP, or Python applications deserialize untrusted data via ObjectInputStream, unserialize, pickle, or similar mechanisms that may lead to RCE, file access, or privilege escalation.
By yaklang · 3,012 installs
npx skills add yaklang/hack-skills --skill deserialization-insecure
Source repository · Upstream listing
SKILL: Insecure Deserialization — Expert Attack Playbook
AI LOAD INSTRUCTION : Expert deserialization techniques across Java, PHP, and Python. Covers gadget chain selection, traffic fingerprinting, tool usage (ysoserial, PHPGGC), Shiro/WebLogic/Commons Collections specifics, Phar deserialization, and Python pickle abuse. Base models often miss the distinction between finding the sink and finding a usable gadget chain.
0. RELATED ROUTING
[jndi injection](../jndi injection/SKILL.md) when deserialization leads to JNDI lookup (e.g., post JDK 8u191 bypass via LDAP → deserialization)
[unauthorized access common services](../unauthorized access common services/SKILL.md) when the deserialization endpoint is an exposed management service (RMI Registry, T3, AJP)
[ghost bits cast attack](../ghost bits cast attack/SKILL.md) when a WAF blocks your BCEL ClassLoader or Fastjson @type payload — Ghost Bits wraps each bytecode byte in a Unicode char whose low 8 bits match, yielding a payload the WAF cannot fingerprint
Advanced Reference
Also load [JAVA GADGET CHAINS.md](./JAVA GADGET CHAINS.md) when you need:
Java gadget chain version compatibility matrix (CommonsCollections 1–7, CommonsBeanutils, Spring, JDK only, Groovy, Hibernate, ROME, C3P0, etc.)
SnakeYAML gadget (ScriptEngineManager/URLClassLoader) with exploit JAR structure
Hessian/Kryo/Avro/XStream deserialization patterns and traffic fingerprints
.NET ViewState deserialization (machineKey requirement, ViewState forgery with ysoserial.net, Blacklist3r)
Ruby YAML.load vs YAML.safe load exploitation with version specific chains
Detection fingerprints: magic bytes table by format (Java AC ED , .NET AAEAAD , Python pickle 80 0N , PHP O: , Ruby 04 08 )
1. TRAFFIC FINGERPRINTING — IS IT DESERIALIZATION?
Java Serialized Objects
Indicator Where to Look
Hex ac ed 00 05 Raw binary in request/response body, cookies, POST params
Base64 rO0AB Cookies ( rememberMe ), hidden form fields, JWT claims
Content Type: application/x java serialized object HTTP headers
T3/IIOP protocol traffic WebLogic ports (7001, 7002)
PHP Serialized Objects
Indicator Where to Look
O:NUMBER:"ClassName" pattern POST body, cookies, session files
a:NUMBER:{ (array) Same locations
phar:// URI usage File operations accepting user controlled paths
Python Pickle
Indicator Where to Look
Hex 80 03 or 80 04 (protocol 3/4) Binary data in requests, message queues
Base64 encoded binary blob API params, cookies, Redis values
pickle.loads / pickle.load in source Code review / whitebox
2. JAVA — GADGET CHAINS AND TOOLS
ysoserial — Primary Tool
URLDNS — Safe Confirmation Probe
URLDNS triggers a DNS lookup without RCE — safe for confirming deserialization without damage:
DNS hit on collaborator = confirmed deserialization. Then escalate to RCE chains.
Commons Collections — The Classic Chain
The vulnerability exists when org.apache.commons.collections (3.x) is on the classpath and the application calls readObject() on untrusted data.
Key classes in the chain: InvokerTransformer → ChainedTransformer → TransformedMap → triggers Runtime.exec() during deserialization.
Apache Shiro — rememberMe Deserialization
Shiro uses AES CBC to encrypt serialized Java objects in the rememberMe cookie.
Attack flow :
1. Detect: response sets rememberMe=deleteMe cookie on invalid session
2. Generate ysoserial payload (CommonsCollections6 recommended for broad compat)
3. AES CBC encrypt with known key + random IV
4. Base64 encode → set as rememberMe cookie value
5. Send request → server decrypts → deserializes → RCE
DNSLog confirmation (before full RCE): use URLDNS chain → java jar ysoserial.jar URLDNS "http://xxx.dnslog.cn" → encrypt → set cookie → check DNSLog for hit.
Post fix (random key) : Key may still leak via padding oracle, or another CVE (SHIRO 721).
WebLogic Deserialization
Multiple vectors:
T3 protocol (port 7001): direct serialized object injection
XMLDecoder (CVE 2017 10271): XML based deserialization via /wls wsat/CoordinatorPortType
IIOP protocol : alternative to T3
Java RMI Registry
RMI Registry (port 1099) accepts serialized objects by design:
JDK Version Constraints
JDK Version Impact
< 8u121 RMI/LDAP remote class loading works
8u121 8u190 trustURLCodebase=false for RMI; LDAP still works
= 8u191 Both RMI and LDAP remote class loading blocked
= 8u191 bypass Use LDAP → return serialized gadget object (not remote class)
3. PHP — unserialize AND PHAR
Magic Method Chain
PHP deserialization triggers magic methods in order:
Attack : craft a serialized object whose destruct() or wakeup() triggers dangerous operations (file write, SQL query, command execution, SSRF).
Serialized Object Format
phpMyAdmin Configuration Injection (Real World Case)
phpMyAdmin PMA Config class reads arbitrary files via source property:
PHPGGC — PHP Gadget Chain Generator
Phar Deserialization
Phar archives contain serialized metadata. Any file operation on a phar:// URI triggers deserialization — even when unserialize() is never directly called.
Triggering functions (partial list):
Attack flow :
1. Upload a valid file (e.g., JPEG with phar polyglot)
2. Trigger file operation: file exists("phar://uploads/avatar.jpg")
3. PHP deserializes phar metadata → gadget chain executes
4. PYTHON — PICKLE
reduce Method
Python's pickle.loads() calls reduce () on objects during deserialization, which can return a callable + args:
Analyzing Pickle Opcodes
Common Python Deserialization Sinks
Defensive Bypass: RestrictedUnpickler
Even when RestrictedUnpickler.find class is used, check if the whitelist is too broad:
If safe builtins includes eval , exec , or import → still exploitable.
5. DETECTION METHODOLOGY
6. DEFENSE AWARENESS
Language Mitigation
Java JEP 290 deserialization filters; whitelist allowed classes; avoid ObjectInputStream on untrusted data; use JSON/Protobuf instead
PHP Avoid unserialize() on user input; use json decode() instead; block phar:// in file operations
Python Use pickle only for trusted data; use json for external input; PyYAML: always use yaml.safe load()
7. QUICK REFERENCE — KEY PAYLOADS
8. RUBY DESERIALIZATION
Ruby Marshal
Marshal.load on untrusted data → RCE
Fingerprint: binary data, no common text header
Gadget chains exist for various Ruby versions
Docker verification: hex payload via [hex string].pack("H ")
Ruby YAML (YAML.load)
YAML.load (not YAML.safe load ) executes arbitrary Ruby objects
Pre Ruby 2.7.2 : Gem::Requirement chain → git set: id / git set: sleep 600
Ruby 2.x 3.x : Gem::Installer → TarReader → Kernel system chain (longer, multi step)
Always test: YAML.load(" !ruby/object:Gem::Installer\ni: x") for class instantiation check
Payload template:
Note: YAML.safe load is safe (Ruby 2.1+); Psych.safe load also safe
9. .NET DESERIALIZATION
Traffic fingerprint :
BinaryFormatter: hex AAEAAD (base64 AAEAAAD///// )
ViewState: hex FF01 or /w prefix
JSON.NET: $type property in JSON
BinaryFormatter (most dangerous, deprecated in .NET 5+): arbitrary type instantiation
XmlSerializer : ObjectDataProvider + XamlReader chain for command execution
NetDataContractSerializer : similar to BinaryFormatter, full type info in XML
LosFormatter : used in ViewState, deserializes to ObjectStateFormatter
JSON.NET : $type property enables type control → ObjectDataProvider + ExpandedWrapper chains
Tool : ysoserial.net — generate payloads for all .NET formatters
POP gadgets : ObjectDataProvider , ExpandedWrapper , AssemblyInstaller.set Path
10. NODE.JS DESERIALIZATION
node serialize : unserialize() with IIFE (Immediately Invoked Function Expression)
Payload marker: $$ND FUNC$$
Add () at end to auto execute:
funcster : js function property → constructor.constructor to access process
cryo : similar to funcster, serializes JS objects with function support
RUBY DESERIALIZATION
Marshal (Binary Format)
YAML.load (Critical — Most Common Ruby Deser Sink)
Tools
elttam/ruby deserialization — Ruby gadget chain generator
frohoff/ysoserial inspiration → check Ruby specific forks
.NET DESERIALIZATION
Traffic Fingerprinting
Indicator Serializer
Hex 00 01 00 00 00 / Base64 AAEAAD BinaryFormatter
Hex FF 01 / Base64 /w DataContractSerializer
ViewState starts with VIEWSTATE LosFormatter / ObjectStateFormatter
JSON with $type property JSON.NET (Newtonsoft) TypeNameHandling
XML with <ObjectDataProvider XmlSerializer / NetDataContractSerializer
BinaryFormatter / LosFormatter
XmlSerializer + ObjectDataProvider
JSON.NET with TypeNameHandling
Vulnerable when TypeNameHandling is set to Auto , Objects , Arrays , or All .
Tools
pwntester/ysoserial.net — primary .NET deserialization payload generator
Gadget chains: TypeConfuseDelegate, TextFormattingRunProperties, PSObject, ActivitySurrogateSelectorFromFile
NODE.JS DESERIALIZATION
node serialize (IIFE Pattern)
funcster
PHP create function + Deserialization Combo
11. RUBY DESERIALIZATION
Marshal
YAML (CVE rich surface)
Tools : elttam/ruby deserialization , mbechler/ysoserial (Ruby variant)
12. .NET DESERIALIZATION
Fingerprinting
Magic Bytes Format
AAEAAD (base64) / 00 01 00 00 00 (hex) BinaryFormatter
FF 01 or /w (base64) ViewState (ObjectStateFormatter)
< (XML opening) XmlSerializer / DataContractSerializer
JSON with $type key JSON.NET (TypeNameHandling enabled)
BinaryFormatter (most dangerous)
ViewState (ASP.NET)
XmlSerializer + ObjectDataProvider
JSON.NET ($type abuse)
Vulnerable when TypeNameHandling != None in JSON deserialization settings.
Tools
pwntester/ysoserial.net — primary .NET gadget chain generator
NotSoSecure/Blacklist3r — decrypt/forge ViewState with known machineKey
13. NODE.JS DESERIALIZATION
node serialize (IIFE injection)
funcster
PHP create function + Deserialization Combo