deserialization
Skill1 starsChanged 11 days agoMITView on GitHub
Hunt for insecure deserialization: identify serialization formats in transit (Java ObjectInputStream, PHP serialize/unserialize, Python pickle, .NET BinaryFormatter/ ViewState, Ruby Marshal), assess library/framework versions against known gadget-chain CVEs, and confirm whether untrusted input actually reaches a deserialization sink. Use whenever a request/response/cookie carries a binary blob, a base64 value with a serialization magic byte, or a framework known to deserialize client-controlled state (Java app servers, PHP apps with session/cache serialization, .NET ViewState, Python pickle-based caches/queues). Keywords: deserialization, ObjectInputStream, gadget chain, ysoserial, PHP unserialize, Python pickle, .NET BinaryFormatter, ViewState, Java RMI, Marshal.load, ACE via deserialization. Do NOT use for generic object-injection in templating engines (that's ssti) or for prototype pollution in JS (prototype-pollution) — this skill is specifically about native serialization formats reconstructing objects/state from untrusted bytes.
5 other projects use a version of this.
Adopted by
Most recently taken up by
- ferr079/claude-code-cybersec-skillstheir own version, first seen Oct 12, 2026
- cdxiaodong/cain-agenttheir own version, first seen Oct 8, 2026
- lichtblick-suite/lichtblicktheir own version, first seen Oct 8, 2026
- emre-guler/websectheir own version, first seen Aug 27, 2026
- langbyyi/websec-skillstheir own version, first seen Jun 12, 2026
Other versions5 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 5
- lichtblick-suite/lichtblick★ 1.2ksame name
- cdxiaodong/cain-agent★ 953same name
- langbyyi/websec-skills★ 4same name
- emre-guler/websec★ 2same name
- ferr079/claude-code-cybersec-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository124 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- ai-agent-reconSkill
- ai-supply-chainSkill
- exfiltration-via-aiSkill
- indirect-injectionSkill
- llm-fuzzingSkill
- prompt-injectionSkill
- rag-poisoningSkill
- tool-abuseSkill
- chain-analysisSkill
- chain-auth-to-takeoverSkill
- chain-customSkill
- chain-graph-walkSkill
- chain-idor-to-mass-dataSkill
- chain-info-to-exploitSkill
- chain-multi-appSkill
- chain-ssrf-to-cloudSkill
- chain-web-to-rceSkill
- chain-xss-to-account-takeoverSkill
- email-securitySkill
- engagement-flowSkill
- finding-disciplineSkill
- http-headers-securitySkill
- oob-interactionsSkill
- opsec-disciplineSkill
- research-firstSkill
- scope-disciplineSkill
- scope-importSkill
- session-contextSkill
- 2fa-bypassSkill
- api-abuseSkill
- auth-bypassSkill
- broken-access-controlSkill
- business-logicSkill
- cache-poisoningSkill
- clickjackingSkill
- corsSkill
- credential-testingSkill
- crlf-injectionSkill
- cryptographic-oracleSkill
- csrfSkill
- css-injectionSkill
- data-exfiltration-testSkill
- email-injectionSkill
- file-uploadSkill
- fuzzingSkill
- graphqlSkill
- grpcSkill
- host-headerSkill
- http-smugglingSkill
- idorSkill
- info-disclosureSkill
- jwtSkill
- lateral-movementSkill
- lfi-rfiSkill
- mass-assignmentSkill
- oauthSkill
- open-redirectSkill
- parameter-pollutionSkill
- password-resetSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
4 rules. 0 are common, 3 are distinctive, and 1 is very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
3
Distinctive
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 90
If no version-matched chain is known, this stays Unproven/Inferred — do not improvise a chain against an unconfirmed version.
- Very specific: line 146
Every claim above "format identified" needs the exact payload sent and the exact observable response/callback captured, labeled …
- Distinctive: line 166
Never aim a gadget chain directly at destructive code execution as a first test — use a non-destructive canary (DNS/HTTP callback, sleep) …
- Distinctive: line 172
Before declaring this finding complete, probe these escalation paths:
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Signals
- Base64 or raw binary values in cookies, hidden form fields, or request bodies that decode
to a recognizable serialization magic byte/header:
- Java:
0xAC 0xED(hex) at the start of the decoded bytes. - PHP
serialize(): strings starting with a type-length prefix likea:,O:,s:,i:. - Python
pickle: opcodes starting with\x80(protocol 2+) or printable opcodes for protocol 0 ((dp0,c__main__, etc.). - .NET
BinaryFormatter/ViewState: base64 blobs, ViewState (__VIEWSTATE) with a/wEP...prefix when MAC validation is absent or disabled. - Ruby
Marshal: binary blobs starting with a version byte pair like\x04\x08.
- Java:
- Framework/library fingerprint from recon (via
tech-stack-fingerprint) matches a known vulnerable serialization library version (e.g., old Apache Commons Collections, old Jackson with polymorphic typing enabled, old PHP frameworks with known unserialize gadget classes, .NET ViewState withoutEnableViewStateMac). - Error messages on malformed input mentioning
ObjectInputStream,readObject,ClassNotFoundException,unserialize(): Error at offset,pickle.UnpicklingError, or.NETdeserialization exceptions — these confirm a deserialization sink exists even before any gadget chain is attempted. - Caching/session layers (Redis, Memcached, session files) known to store serialized PHP/ Java objects, reachable indirectly through another vuln (SSRF, LFI) that lets you write to the store.
Prerequisites
- Confirmed reachable sink: a parameter, cookie, or header whose value is deserialized server-side. Passive confirmation (magic bytes + framework fingerprint) is enough to start; active confirmation (step 3 below) is required before claiming anything beyond "format identified."
- Knowledge of the exact library/version in use — gadget chain availability is entirely version-dependent. Do not attempt generic chains against an unidentified version.
- Explicit scope and gate confirmation before any object-instantiation test, per project rules — these tests can cause side effects (resource exhaustion, state corruption, in the worst case code execution) even when "just testing."
Methodology
- Format identification (passive). Decode every binary/base64-looking value observed
in requests and responses and classify by magic bytes/structure:
For PHP, inspect the raw (often un-encoded) cookie/param value directly for theecho "$VALUE" | base64 -d | xxd | head -5 # Java: starts with ac ed 00 05 # .NET BinaryFormatter: starts with 00 01 00 00 ... or similar header patterna:N:{...}/O:N:"ClassName":M:{...}structure. - Sink confirmation via malformed input (passive/low-risk). Send a syntactically
invalid but harmless payload of the same format and inspect the error:
A deserialization-specific error (as listed under Signals) confirms the sink exists. A generic 400/401 with no framework-specific trace means you have not yet confirmed a reachable sink — stop here and mark as Unproven rather than assuming.curl -s -i https://target/endpoint \ -H "Cookie: session=TRUNCATED_BASE64_FRAGMENT" - Version-matched gadget-chain research (before any active test). With the exact
library/version from recon, check whether a public gadget chain exists for that version
(
ysoserialpayload list for Java,phpggcgadget chain list for PHP, known-vulnerableJackson/Fastjsonpolymorphic type configs, known .NETObjectDataProviderchains). If no version-matched chain is known, this stays Unproven/Inferred — do not improvise a chain against an unconfirmed version. - Side-effect probe (requires explicit gate). With operator authorization, use a
version-matched, non-destructive gadget (e.g., one that triggers a DNS lookup, a sleep,
or writes an identifiable canary file to a scratch path) rather than a gadget chain aimed
directly at code execution, to separate "deserialization triggers attacker-controlled
object construction" from "and that construction has a dangerous side effect":
# example shape only — exact invocation depends on the matched library/version ysoserial -p <MatchedPayload> -c "nslookup canary.yourdomain.com" > payload.ser curl -s -i https://target/endpoint --data-binary @payload.ser # confirm the DNS lookup arrived at your controlled resolver/listener - For .NET ViewState specifically, check whether
EnableViewStateMacandViewStateEncryptionModeare both effectively disabled before assuming forgeable ViewState is viable — most current frameworks default this on, and a tampered ViewState failing MAC validation (visible as a generic error, not a deserialization trace) is a different, weaker finding (integrity check working as intended) than a successful bypass. - Confirm no secondary mitigation is masking a true negative, e.g.,
ObjectInputFilter/ look-ahead deserialization allow-listing on the JVM, PHP__wakeup/__destructhardening, or a WAF rule specific to known gadget chain signatures — a blocked request with a WAF fingerprint is a different finding than "deserialization sink doesn't exist."
Tooling
ysoserial— generates Java gadget-chain payloads for known library/version combinations; only useful once the exact vulnerable dependency is confirmed.phpggc— equivalent gadget-chain generator for PHP object-injection chains.- Burp Suite's Java Deserialization Scanner extension — passive detection of serialized-object patterns in traffic plus semi-automated gadget probing.
xxd/base64— manual byte-level inspection, the first and cheapest step every time.
Root Causes
- Server-side code calling a native deserialization API (
ObjectInputStream.readObject, PHPunserialize(), Pythonpickle.loads(), .NETBinaryFormatter.Deserialize, RubyMarshal.load) directly on attacker-controlled bytes, with no type allow-list. - Vulnerable gadget classes present on the classpath/dependency tree (common transitively through unrelated libraries) that can be chained into dangerous behavior once any deserialization entry point exists.
- Integrity controls (HMAC/signing) on serialized state either absent or not actually verified before deserialization occurs.
Validation Gate (minimum proof)
- Minimum: confirmed object instantiation or an observable side effect attributable to the deserialization process — a canary DNS/HTTP callback, a confirmed sleep/delay, a file written to a path you control, or an identifiable exception stack trace showing gadget class construction. Format identification alone (step 1) is not sufficient to report beyond "serialization format identified, sink unconfirmed."
- Full exploitation (code execution) is a separate, higher gate requiring explicit operator authorization per project rules — do not escalate from a canary callback straight to an RCE claim without that separate step and sign-off.
- Every claim above "format identified" needs the exact payload sent and the exact observable response/callback captured, labeled Demonstrated/Inferred/Unproven.
Gotchas
- Overclaim trap: detecting a known-vulnerable library version on the classpath is Inferred at most, never Demonstrated, until an actual payload produces an observable side effect — per project anti-fabrication rules, "Commons Collections 3.1 on classpath" is not itself a finding.
- Overclaim trap: a 500 error after sending a malformed serialized blob is not proof of deserialization — many frameworks throw a generic exception for any malformed body regardless of content type. Confirm the error trace is specific to a deserialization call path, not just "any parse error."
- Common N/A:
ObjectInputFilter/allow-list deserialization, signed/HMAC-validated serialized state actually verified before use, or a framework that has fully migrated off native serialization (e.g., JSON-only session storage) — verify the control is real (not just present in config) before closing. - Gadget chains are brittle across minor versions — a chain working on 3.1 failing on 3.2.1 is expected and not evidence the app is safe; it only means that specific chain doesn't apply.
- Never aim a gadget chain directly at destructive code execution as a first test — use a non-destructive canary (DNS/HTTP callback, sleep) to confirm the primitive before any escalation, and only with explicit operator sign-off per the human-gate rules.
Chain Anchors
Before declaring this finding complete, probe these escalation paths:
- Gadget chain to RCE — Does a known gadget chain for the library/framework in use achieve full RCE, not just object instantiation or a crash?
- DoS via recursive/oversized payload — Can a crafted payload (deeply nested, billion-laughs-style) cause resource exhaustion?
- Property/field injection — Does deserializing attacker-controlled data let you set internal fields that bypass app-level validation (role, balance, ownership)?
- Blind deserialization confirmation — If no direct output is visible, can you confirm execution via an out-of-band channel (DNS/HTTP callback)?
- Cross-service reach — Is the vulnerable deserialization reachable from an internal queue/message bus, widening the attack surface beyond the HTTP API?
A finding without chain anchor results is INCOMPLETE. Record each anchor as tested/not-applicable/blocked with the reason.
Chains & Compositions
- Confirmed side effect with a code-execution-capable gadget → feeds rce for the full exploitation assessment (separate gate).
- Deserialization sink reachable only after another vuln grants write access to a cache/ session store (SSRF to internal Redis, LFI to a session file) → chain with those skills in chain-analysis.
- Version/library fingerprint feeding this hunt comes from tech-stack-fingerprint; keep that recon current before re-testing after a deploy.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

