Share
## https://sploitus.com/exploit?id=05D25E0C-E7B8-5032-BCDB-055C9CEC2AE6
# camel-netty-http / camel-vertx-http HTTP-Response Unsafe Deserialization Reproducer (CVE-2026-40859)

This project demonstrates a **Java deserialization vulnerability** in Apache Camel's `camel-netty-http`
and `camel-vertx-http` components, tracked as **CVE-2026-40859**. When a producer endpoint is configured
with `transferException=true` (or the component-level `allowJavaSerializedObject=true`), a **backend HTTP
response** with a failure status and `Content-Type: application/x-java-serialized-object` has its body
deserialized with a raw `java.io.ObjectInputStream` and **no `ObjectInputFilter`**. An attacker who
controls the backend the Camel producer talks to โ€” a compromised service, or a man-in-the-middle on a
plain-HTTP connection โ€” can return a crafted serialized object and, if a gadget chain is on the
classpath, achieve **remote code execution** on the Camel host.

Advisory: https://camel.apache.org/security/CVE-2026-40859.html

## Vulnerability Summary

| Property | Value |
|----------|-------|
| **Components** | `camel-netty-http`, `camel-vertx-http` (producer side) |
| **Affected Class** | `org.apache.camel.component.netty.http.NettyHttpHelper#deserializeJavaObjectFromStream` (and `VertxHttpHelper#deserializeJavaObjectFromStream`) |
| **CWE** | CWE-502: Deserialization of Untrusted Data |
| **Impact** | Remote Code Execution (RCE) |
| **Precondition** | `transferException=true` (or `allowJavaSerializedObject=true`) + `throwExceptionOnFailure=true` (default) + attacker-controlled backend |
| **Affected Versions** | From 4.0.0 before 4.14.8, from 4.15.0 before 4.18.3, from 4.19.0 before 4.20.0 |
| **Fixed Versions** | 4.14.8, 4.18.3, 4.20.0 |
| **JIRA** | CAMEL-23324 |
| **Reporter** | Venkatraman Kumar (Securin) |

> **Not exploitable in the default configuration** โ€” `transferException` defaults to `false`. The PoC
> enables it, as an application that wants remote-exception propagation would.

## Technical Details

On a non-2xx response, the netty-http producer (with `throwExceptionOnFailure=true`, the default) builds
an exception from the response via `populateNettyHttpOperationFailedException`. If `transferException` is
on and the response carries the serialized-object content type, it deserializes the body:

```java
// NettyHttpHelper.populateNettyHttpOperationFailedException(...) - affected version
if (transferException) {
    String contentType = response.headers().get(NettyHttpConstants.CONTENT_TYPE);
    if (NettyHttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT.equals(contentType)) {   // application/x-java-serialized-object
        InputStream is = exchange.getContext().getTypeConverter().convertTo(InputStream.class, response);
        if (is != null) {
            Object body = deserializeJavaObjectFromStream(is);   //  In a real attack the serialized bytes are produced offline by the attacker (e.g. with **ysoserial**);
> only the **victim** needs the gadget chain on its classpath. This PoC builds the gadget in-process for
> convenience, which is why the JVM is started with `--add-opens java.base/java.util=ALL-UNNAMED` โ€” that
> flag is a gadget-construction detail, unrelated to the vulnerability.

## Prerequisites

- Java 17+ and Maven 3.8+
- Docker (runs the reproducer)

## Reproduction Steps

### Step 1: Build and start the container

```bash
mvn clean package -DskipTests
docker compose up -d --build
```

### Step 2: Trigger the deserialization (RCE)

```bash
curl -s http://localhost:8080/exploit/attack
# -> producer threw ...NettyHttpOperationFailedException  (expected)
#
#    >>> RCE proof โ€” /tmp/pwned exists: true
```

### Step 3: Verify

```bash
docker exec cve-2026-40859 ls -la /tmp/pwned
```

### Cleanup

```bash
docker compose down
```

## Attack Vectors

Any camel-netty-http / camel-vertx-http **producer** configured with `transferException=true` (or
`allowJavaSerializedObject=true`) that talks to a backend an attacker can control or intercept:

- A **man-in-the-middle** on an unencrypted (`http://`) producer connection substitutes the response.
- A **compromised or malicious backend** service returns the crafted response directly.

## Exploit Conditions

1. Producer with `transferException=true` (or component `allowJavaSerializedObject=true`).
2. `throwExceptionOnFailure=true` (the default).
3. An attacker-controlled/interceptable backend returning `5xx` + `application/x-java-serialized-object`.
4. **A gadget library on the classpath** (here `commons-collections:3.2.1`).

## Recommended Fix

Upgrade to **4.14.8 / 4.18.3 / 4.20.0**. The fix constrains both helpers with a default
`ObjectInputFilter` allow-list (`java.**;javax.**;org.apache.camel.**;!*`), customisable via the new
`deserializationFilter` endpoint option or the JVM-wide `-Djdk.serialFilter` system property.

## Mitigation

Until upgrading:

1. **Do not enable** `transferException=true` / `allowJavaSerializedObject=true` on producers talking to
   untrusted or network-reachable backends.
2. Use **TLS (`https`)** for producer connections so responses cannot be substituted in transit.
3. Where the option is required, set an explicit allow-list:
   `-Djdk.serialFilter=java.**;org.apache.camel.**;!*`.
4. **Remove gadget libraries** from the classpath (upgrade/remove commons-collections 3.x and similar).

## Disclaimer

This reproducer is provided for **security research and authorized testing only**, for a **publicly
disclosed and fixed** vulnerability. Do not use it against systems without explicit permission.