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文件枚举, 中间件安全, 反序列化, 域名枚举, 漏洞复现, 请求拦截