oscerd/CVE-2026-43866
GitHub: oscerd/CVE-2026-43866
Apache Camel camel-jms 组件 CVE-2026-43866 反序列化过滤绕过漏洞的概念验证与复现项目。
Stars: 0 | Forks: 0
# camel-jms Forged DefaultExchangeHolder Filter-Bypass 复现项目 (CVE-2026-43866)
本项目演示了 **CVE-2026-43866**,这是对 Apache Camel 的
`camel-jms`(以及 `camel-sjms` / JMS 系列)组件中 **CVE-2026-40860 修复方案的绕过**。CVE-2026-40860 针对传入的 JMS `ObjectMessage` payload 添加了反序列化后的类
允许列表(`java.**;javax.**;org.apache.camel.**;!*`)。但是
`org.apache.camel.support.DefaultExchangeHolder` 位于允许列表中的 `org.apache.camel.**` 命名空间内,因此
如果一个 `ObjectMessage` 的顶层对象**是** `DefaultExchangeHolder`,它将通过检查。接收端
随后会在**不需要** `transferExchange` 的情况下对其调用 `DefaultExchangeHolder.unmarshal()` —— 将持有者的所有
非空字段写入到路由的 Exchange 中(body、IN/OUT headers、exchange properties、variables、
exchange id、exception)。能够发布 `ObjectMessage` 的攻击者因此可以**仅使用普遍受信任的 `java.*` 类型注入任意的 Exchange
状态——无需反序列化 gadget 链**——从而
操纵路由、headers、properties 和错误处理。
安全公告: https://camel.apache.org/security/CVE-2026-43866.html
## 漏洞概述
| 属性 | 值 |
|----------|-------|
| **组件** | `camel-jms` (+ `camel-sjms`, `camel-sjms2`, `camel-amqp`, `camel-activemq`, `camel-activemq6`) |
| **受影响类** | `org.apache.camel.component.jms.JmsBinding#extractBodyFromJms` → `DefaultExchangeHolder.unmarshal` |
| **CWE** | CWE-502 (Deserialization of Untrusted Data) + CWE-20 (Improper Input Validation) |
| **影响** | Exchange 状态注入:攻击者控制的 body、headers、properties、variables、exception |
| **性质** | 对 CVE-2026-40860 类过滤修复的**绕过**(并非其自身的缺陷) |
| **受影响版本** | 从 3.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-23373 (jms), CAMEL-23409 (sjms) |
| **报告者** | gaorenyusi |
## 技术细节
```
// JmsBinding.extractBodyFromJms(...) - affected 4.18.2
if (message instanceof ObjectMessage objectMessage) {
Object payload = objectMessage.getObject();
checkDeserializedClass(payload); // CVE-2026-40860 allow-list: java.**;javax.**;org.apache.camel.**;!*
if (payload instanceof DefaultExchangeHolder holder) { // <-- DefaultExchangeHolder is org.apache.camel.** -> passes
DefaultExchangeHolder.unmarshal(exchange, holder); // <-- writes forged state into the Exchange; NO transferExchange gate
Map jmsHeaders = extractHeadersFromJms(message, exchange);
exchange.getIn().getHeaders().putAll(jmsHeaders);
return exchange.getIn().getBody();
} else {
return payload;
}
}
```
不对称性在于:**发送**端控制着 `ObjectMessage`/`transferExchange` 的创建,但**接收**端
会对其反序列化的任何 `DefaultExchangeHolder` 进行 unmarshal。修复方案(4.14.8 / 4.18.3 / 4.21.0)添加了一个新的
`objectMessageEnabled` 选项(`security = "insecure:serialization"`,默认为 **false**)—— 除非显式启用,否则传入的
`ObjectMessage` 根本不会被反序列化,因此伪造的 holder 永远无法到达
`unmarshal()`。(对于依赖于 `ObjectMessage` / `transferExchange` 的路由来说,这是一个破坏性变更。)
## 受害者路由
```
from("jms:queue:cve") // mapJmsMessage defaults to true; transferExchange NOT set
.process(exchange -> { /* observes the injected body / headers / properties */ });
```
## 仓库结构 — 攻击者 vs. 受害者
**受害者**是 Camel JMS consumer。**攻击者**是任何可以发布到队列的 producer。双方
都通过 Docker 与真实的 **Apache ActiveMQ Artemis** broker 进行通信。
```
CVE-2026-43866/
├── pom.xml # camel-jms 4.18.2 + activemq-client 6.2.4 (NO gadget library)
├── Dockerfile # runs the app (no --add-opens; no gadget)
├── docker-compose.yml # Artemis broker (quay.io) + the reproducer app
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── JmsConfig.java # OpenWire ConnectionFactory (trustedPackages incl. org.apache.camel) + jms component
│ ├── VictimRoute.java # victim: from("jms:queue:cve"); records what the route observed
│ ├── CapturedState.java
│ ├── ForgedHolderFactory.java # builds a DefaultExchangeHolder via the public marshal() API
│ └── ExploitController.java # attacker: publishes the forged holder as an ObjectMessage
└── resources/
└── application.properties
```
## 前置条件
- Java 17+ 和 Maven 3.8+
- Docker(用于运行 broker 和应用程序)
## 复现步骤
### 步骤 1:构建并启动一切
```
mvn clean package -DskipTests
docker compose up -d --build
```
### 步骤 2:触发绕过
```
curl -s http://localhost:8080/exploit/attack
# -> 已将伪造的 DefaultExchangeHolder 作为 JMS ObjectMessage 发布到队列 'cve'。
# ...
# body = INJECTED-BODY-... (injected: true)
# header = pwned-header-... (injected: true)
# property = pwned-property-... (injected: true)
# # >>> Exchange-state injection 证明 — 攻击者控制了 body+header+property: true
```
该路由在运行时带有它从未设置过的 body、header 和 property —— 这些全是由攻击者伪造的 holder 提供的。
### 清理
```
docker compose down
```
## 攻击向量
任何 Camel JMS **consumer**(`camel-jms`、`camel-sjms`、`camel-sjms2`、`camel-amqp`、`camel-activemq`、
`camel-activemq6`),只要配置了 `mapJmsMessage=true`(默认值),并且从攻击者可以发布消息的 destination 中读取数据即可。在 consumer 端**不需要**启用 `transferExchange`。
## 利用条件
1. 一个 Camel JMS consumer 配置了 `mapJmsMessage=true`(默认值),并且运行在受影响的版本上。
2. 攻击者能够将 payload 为 `DefaultExchangeHolder` 的 `ObjectMessage` 加入队列。
3. JMS provider 会反序列化该 payload —— 对于任何使用 `transferExchange` 的部署来说,这意味着
该 provider 已经信任了 `org.apache.camel`。**不需要任何 gadget 库。**
## 推荐修复方案
升级到 **4.14.8 / 4.18.3 / 4.21.0**(CAMEL-23373 / CAMEL-23409)。JMS `ObjectMessage` 处理已通过新的
`objectMessageEnabled` 选项默认禁用;请仅针对完全由受信任的 producer 提供数据的 destination 启用该功能。
## 缓解措施
在升级之前:
1. 通过 JMS broker 授权,将 Camel 消费的 queues/topics 的发布权限限制为**受信任的 producer**。
2. 不要将映射 `ObjectMessage` body 的 JMS consumer 暴露给不受信任的网络。
3. 注意:JMS provider 的反序列化允许列表**不能**缓解此特定的绕过攻击(因为 payload 仅使用
普遍受信任的类以及 `DefaultExchangeHolder`)。
## 免责声明
本复现项目仅用于**安全研究和授权测试**,针对的是**已公开披露并已修复**的
漏洞。未经明确许可,请勿将其用于攻击任何系统。
标签:Apache Camel, CISA项目, JMS, JS文件枚举, 中间件安全, 反序列化, 域名枚举, 漏洞复现, 请求拦截