# Java Insecure Deserialization: From Untrusted Data to RCE

**Insecure deserialization** occurs when an application reconstructs objects from **attacker-controlled serialized data**.

In Java, this can become extremely dangerous when existing classes can be chained together to reach a **dangerous operation such as command execution**.

The most important question is:

> **How does a serialized object actually turn into RCE?**

* * *

## 1\. Serialization vs. Deserialization

### Serialization

An application converts an object into data that can be stored or transmitted.

```text
Object
  ↓
Serialized Data / Bytes
```

### Deserialization

The application reconstructs the object from that data.

```text
Serialized Data / Bytes
  ↓
Object
```

The vulnerability appears when the serialized data is **controlled or influenced by an attacker**.

```text
Attacker-Controlled Data
          ↓
     Deserialization
          ↓
       Object Graph
          ↓
    Dangerous Behavior
          ↓
          RCE
```

* * *

# 2\. Why Can Deserialization Become RCE?

Deserialization itself does **not automatically mean RCE**.

The real danger comes from the behavior of classes involved in the object graph.

An application may already contain classes that perform interesting or dangerous operations when certain methods are triggered.

An attacker can chain these legitimate classes together into a **gadget chain**.

Think of it like dominoes:

```text
Malicious Serialized Object
          ↓
       Gadget 1
          ↓
       Gadget 2
          ↓
       Gadget 3
          ↓
    Dangerous Sink
          ↓
    Command Execution
          ↓
          RCE
```

A **gadget** is an existing class or method whose behavior can be used as one step in such a chain.

Importantly, the classes themselves don't necessarily need to be malicious.

* * *

# 3\. Does the Dangerous Class Have to Be Present?

## Yes — generally, for a classic gadget-chain attack.

This is one of the most important concepts to understand about Java deserialization.

Suppose a gadget chain requires classes from a particular library:

```text
Library.GadgetA
      ↓
Library.GadgetB
      ↓
Dangerous Operation
```

Those classes generally need to be **available to the target JVM/classloader**.

The attacker normally **cannot simply reference an arbitrary nonexistent class** in the serialized payload and expect Java to instantiate it.

Conceptually:

```text
Serialized Payload
       ↓
References GadgetA
       ↓
Can target JVM resolve GadgetA?
       ↓
    ┌───────┴───────┐
    │               │
   YES              NO
    │               │
    ↓               ↓
Continue         Chain fails
```

If the required library isn't present:

```text
Attacker Payload
      ↓
Required Gadget Class
      ↓
Class not available
      ↓
❌ Gadget chain fails
```

### The key point

> **For a classic Java deserialization RCE, the classes needed for the gadget chain generally have to be available to the target JVM/classloader.**

The attacker is normally **not uploading a new Java class through the serialized object**.

Instead, the attacker constructs a serialized object that abuses:

**existing classes + existing behaviors + a specific object graph**

to reach a dangerous operation.

* * *

# 4\. Can the Attacker Just Say "Run `Runtime.exec()`"?

Not directly.

The attacker cannot normally put something like:

```text
"Create Runtime object and execute this command"
```

into a serialized payload and expect Java to execute it simply because the string says so.

The attacker needs a **reachable execution path**.

Conceptually:

```text
Attacker-Controlled Object
          ↓
     Existing Class
          ↓
     Existing Class
          ↓
      Gadget Chain
          ↓
Runtime / ProcessBuilder
          ↓
    Command Execution
```

`java.lang.Runtime` is part of the Java platform, so it is normally available.

The difficult part is getting the deserialization process to **reach the dangerous operation** through an exploitable object graph.

So the attack is generally:

> **Abuse existing functionality**

rather than:

> **Create an arbitrary new class**

* * *

# 5\. What If the Gadget Library Isn't Present?

Suppose a known gadget chain requires a particular third-party library.

For example:

```text
Known Gadget Chain
       ↓
Requires Library X
       ↓
Is Library X present?
     ↙       ↘
   NO         YES
   ↓           ↓
Fails       Continue
```

If the library isn't present, **that specific gadget chain generally won't work**.

The attacker would need to find another usable chain based on classes that **are actually available in the target environment**.

This is why dependency and classpath discovery is important during a Java security assessment.

* * *

# 6\. Important: Class Present ≠ Automatically Exploitable

Finding a potentially useful class on the classpath does **not automatically mean RCE is possible**.

Several things need to line up:

```text
Class / Library Present
          ↓
Compatible Gadget
          ↓
Reachable During Deserialization
          ↓
Required Methods Triggered
          ↓
Dangerous Sink Reached
          ↓
         RCE
```

Therefore, during an assessment, ask:

1.  Is deserialization being used?
    
2.  Can an attacker control the serialized input?
    
3.  Which classes/libraries are available?
    
4.  Can those classes form a gadget chain?
    
5.  Does the deserialization configuration permit the required types?
    
6.  Can the chain reach a dangerous sink?
    

* * *

# 7\. What Is a Gadget Chain?

A **gadget chain** is a sequence of existing classes and methods whose combined behavior allows an attacker to reach a desired outcome.

For example:

```text
Gadget A
   ↓
Gadget B
   ↓
Gadget C
   ↓
Dangerous Method
   ↓
Command Execution
```

None of these classes necessarily needs to be malicious.

They may be completely legitimate classes from:

*   The application
    
*   Java libraries
    
*   Third-party dependencies
    
*   Frameworks
    

The security problem comes from how their behaviors can be **combined during deserialization**.

* * *

# 8\. Where Does ysoserial Fit?

**ysoserial** is a well-known Java security testing tool that generates serialized payloads based on known gadget chains.

Conceptually:

```text
Known Gadget Chain
        +
Serialized Object
        ↓
   Payload
        ↓
Target Application
        ↓
Deserialization
        ↓
Gadget Chain
        ↓
Dangerous Sink
        ↓
       RCE
```

But an important point is often missed:

> **A ysoserial payload is not universally exploitable.**

The target environment generally needs the classes and conditions required by that particular gadget chain.

If the required dependency isn't present, the payload may simply fail.

* * *

# 9\. What About HMAC Protection?

HMAC can protect the **integrity** of serialized data.

For example:

```text
Serialized Data
      ↓
   Verify HMAC
      ↓
   Valid?
   ↙    ↘
 NO     YES
 ↓       ↓
Reject  Deserialize
```

This prevents an attacker from simply modifying authenticated serialized data without knowing the secret.

However:

> **HMAC does not make unsafe deserialization inherently safe.**

HMAC provides **integrity/authenticity**.

It does not make arbitrary object reconstruction safe.

If an attacker can somehow produce a valid authenticated serialized object, dangerous objects could still potentially be deserialized.

Therefore:

```text
HMAC
 ↓
Protects Integrity
```

does not mean:

```text
HMAC
 ↓
Safe Deserialization
```

* * *

# 10\. How to Prevent Insecure Deserialization

### 1\. Avoid untrusted native deserialization

Prefer safer data formats such as **JSON** where appropriate.

### 2\. Use strongly typed DTOs

Prefer:

```text
Input → Expected DTO
```

over:

```text
Input → Generic Object
```

### 3\. Disable unsafe polymorphic deserialization

Don't allow the client to freely decide which Java class should be instantiated.

### 4\. Never blindly trust type metadata

Be particularly careful with fields such as:

```text
_type
_class
_TypeId
```

### 5\. Use an allowlist

If polymorphism is genuinely required:

```text
Allowed Types
   ├── Type A ✓
   ├── Type B ✓
   └── Type C ✓

Everything else → Reject
```

### 6\. Validate deserialized data

Validate:

*   Type
    
*   Length
    
*   Format
    
*   Range
    
*   Required fields
    
*   Business rules
    

### 7\. Protect data integrity

Use appropriate mechanisms such as:

*   HMAC/MAC
    
*   Digital signatures
    
*   Authenticated encryption
    

when integrity/authenticity is required.

### 8\. Keep dependencies patched

Gadget chains often depend on third-party libraries.

Maintain an accurate dependency inventory, remove unnecessary libraries, and patch vulnerable dependencies.

### 9\. Apply least privilege

Limit:

*   OS permissions
    
*   Filesystem access
    
*   Database permissions
    
*   Network access
    

Also consider container isolation and egress filtering.

* * *

# 11\. Jackson and `_TypeId_`

Jackson is widely used for JSON serialization/deserialization in Java applications.

One important security concern is **polymorphic deserialization**.

Conceptually:

```text
JSON
 ↓
Type Metadata
 ↓
Which Java Class?
 ↓
Object Creation
```

If an attacker can control type information and the application permits unrestricted type resolution, the attacker may influence which classes are instantiated.

Therefore:

> **Do not allow attacker-controlled** `_TypeId_` **or equivalent type metadata to select arbitrary classes.**

Prefer:

```text
Fixed DTO
   OR
Strict Allowlist of Subtypes
```

over unrestricted polymorphic deserialization.

* * *

# 12\. The Complete Mental Model

When assessing a Java application, think about insecure deserialization like this:

```text
       Is Deserialization Used?
                 ↓
                YES
                 ↓
     Is Input Attacker-Controlled?
                 ↓
                YES
                 ↓
       What Classes Are Available?
                 ↓
       Can a Gadget Chain Be Built?
             ↙          ↘
           NO            YES
            ↓             ↓
       Chain fails    Can it reach
                     a dangerous sink?
                           ↓
                          YES
                           ↓
                          RCE
```

The most important part is the middle:

```text
Attacker-Controlled Data
          ↓
    Deserialization
          ↓
Existing Classes / Libraries
          ↓
      Gadget Chain
          ↓
    Dangerous Sink
          ↓
          RCE
```

* * *

# ⭐ Key Takeaways

### 1\. Deserialization ≠ RCE

Deserialization becomes dangerous when attacker-controlled data can trigger exploitable behavior.

### 2\. Gadget classes generally need to exist

For a **classic Java deserialization gadget-chain RCE**, the required classes generally need to be available to the target JVM/classloader.

### 3\. The attacker cannot normally invent a nonexistent class

A serialized payload cannot simply say:

> "Instantiate this arbitrary class that doesn't exist on the target."

The JVM must be able to resolve the class.

### 4\. Attackers abuse existing functionality

The attacker generally constructs a serialized object that abuses **classes and behaviors already available in the target environment**.

### 5\. Classpath discovery matters

The available dependencies can determine which gadget chains are possible.

### 6\. A class being present doesn't guarantee exploitation

You still need a **compatible, reachable gadget chain** that can reach a dangerous sink.

### 7\. ysoserial uses known gadget chains

Its payloads depend on the target having the necessary classes and conditions.

### 8\. HMAC protects integrity, not deserialization safety

Verify integrity **before deserialization**, but don't treat HMAC as a replacement for safe deserialization.

* * *

## 🎯 Interview Answer

If an interviewer asks:

**0."For Java deserialization RCE, does the dangerous class need to be present in the application?"**

A strong answer is:

> **For a classic Java deserialization RCE, the classes required for the gadget chain generally need to be available to the target JVM/classloader. The attacker normally cannot simply reference an arbitrary nonexistent class and have Java instantiate it. Instead, the attacker constructs a serialized object that abuses classes and behaviors already available in the target environment, chaining them together until the execution reaches a dangerous sink such as command execution.**

And the simplest mental model is:

```text
Untrusted Serialized Data
          ↓
     Deserialization
          ↓
Existing Classes
          ↓
    Gadget Chain
          ↓
 Dangerous Sink
          ↓
         RCE
```

**That's the core concept behind Java insecure deserialization.**

### 1\. What is Insecure Deserialization?

> **Insecure deserialization occurs when an application deserializes attacker-controlled serialized data without properly restricting what objects or classes can be instantiated.**

An attacker may abuse **existing classes and gadget chains** in the application's classpath to trigger unintended behavior, potentially leading to **Denial of Service (DoS), authentication bypass, or Remote Code Execution (RCE)**.

**Remember:**

```text
Untrusted Serialized Data
          ↓
    Unsafe Deserialization
          ↓
   Object / Gadget Chain
          ↓
   Potential RCE / DoS
```

* * *

### 2\. How do you prevent Insecure Deserialization?

> **The best approach is to avoid deserializing untrusted native objects whenever possible. Prefer safe formats such as JSON and deserialize into strongly typed DTOs. If deserialization or polymorphism is required, allowlist only the specific classes/types that the application needs and never trust attacker-controlled type metadata.**

Key controls:

*   **Avoid native deserialization** of untrusted data where possible.
    
*   **Use strongly typed DTOs** instead of generic `Object` types.
    
*   **Allowlist permitted classes/types** and reject everything else.
    
*   **Disable or restrict polymorphic deserialization** where possible.
    
*   **Never trust attacker-controlled type metadata** such as `_type`, `_class`, or `_TypeId_`.
    
*   **Validate deserialized data** including type, format, length, range, and business rules.
    
*   **Protect data integrity** using HMAC/MAC or digital signatures where appropriate, and verify integrity **before deserialization**.
    
*   **Keep dependencies patched** and remove unnecessary libraries that could provide gadget-chain classes.
    
*   **Apply least privilege** so successful exploitation has limited impact.
    

**Interview shortcut:**

```text
Avoid
  ↓
Strongly Typed DTOs
  ↓
Allowlist Classes / Types
  ↓
Restrict Polymorphism
  ↓
Validate
  ↓
Patch Dependencies
  ↓
Least Privilege
```

**For Java/Jackson specifically:**

> **Never allow attacker-controlled type metadata to select arbitrary classes. Use a fixed DTO or a strict allowlist of permitted subtypes/classes.**
