Match PHP deserialization gadgets to installed dependencies
Needs: Required gadget classes and compatible dependency versions are loaded; transport preserves exact serialized bytes
Shell commands
# Baseline
# Inspect available families and the exact chain's version/vector requirements
phpggc -l
phpggc -i Monolog/RCE1
# Example function-call gadget, only when that chain matches the application
phpggc -b Monolog/RCE1 system id > payload.b64
Read: base64 is a transport choice, not a bypass—the sink must decode it before deserialization. Preserve raw serialized lengths and binary bytes; use the encoding that the real request expects. A generated payload is not execution proof. Missing classes, rejected object types or a different dependency version → choose a matching chain or another primitive. Verify a benign effect before selecting a shell payload.
Verify → Require the exact dependency/version, sink and attributable effect; successful payload generation proves none of these.
If it fails → Missing classes, allowed-class restrictions, length corruption or version mismatch defeats the chain; choose only an evidence-matched family. More detail ↓
Explanation & examples
Match PHP deserialization gadgets to installed dependencies
- USE WHEN
- Source or request evidence shows controlled serialized PHP data reaches unsafe unserialize
- STARTING ACCESS
- A reproducible application request and a controlled input or access-context comparison
- RESULT
- A verified gadget effect in the application process context
Recognize the clue
Use source, composer metadata and request format to establish unsafe PHP deserialization and loaded gadget classes before generating bytes.
phpggc -l
phpggc -i Monolog/RCE1
Source sink: unserialize(INPUT)
Installed dependency: compatible Monolog releaseMeans: The sink and loaded class family supply a gadget-chain candidate; generation alone is not execution.
Confirm: Match exact version/vector, preserve serialized lengths/encoding and verify one benign effect.
- After validation
- A compatible chain causes the intended effect: select that dependency-specific route.
- Ruled out in this context
- Required classes are absent or allowed-class restrictions apply: reject that chain.
- Still inconclusive
- Unknown decoding or transport corruption must be resolved before interpreting a failed payload.
Troubleshooting: Missing classes, allowed-class restrictions, length corruption or version mismatch defeats the chain; choose only an evidence-matched family.
Additional prerequisite checks
phpggc -l
phpggc -i Monolog/RCE1
phpggc -b Monolog/RCE1 system id > payload.b64
Use when a controlled serialized value reaches unsafe unserialize() and the required classes are loaded. Identify dependencies/builds from source or composer.lock first.
Read: base64 is a transport choice, not a bypass—the sink must decode it before deserialization. Preserve raw serialized lengths and binary bytes; use the encoding that the real request expects. A generated payload is not execution proof. Missing classes, rejected object types or a different dependency version → choose a matching chain or another primitive. Verify a benign effect before selecting a shell payload.
Sources: upstream 1.
Why it works
A generated gadget chain is dependency-specific. Base64 changes transport only and must match the application's decode path.
Worked example · hypothetical
Observation: composer.lock and source show a compatible loaded chain and unsafe unserialize. Test: generate a minimal benign effect in the real transport. Illustrative output: the controlled effect occurs once. Interpretation: establish process identity before any session payload.
New identity, privilege, host or route? Re-enumerate → All topic tasks →