
Reproducer for CVE-2026-40860 — Apache Camel camel-jms/sjms/amqp JMS ObjectMessage unsafe deserialization (RCE)
本项目演示了 Apache Camel 的 camel-jms 组件中存在的 Java 反序列化漏洞(并间接影响 camel-sjms、camel-sjms2、camel-amqp、camel-activemq、camel-activemq6),该漏洞被跟踪为 CVE-2026-40860。JmsBinding.extractBodyFromJms() 方法在处理传入的 JMS ObjectMessage 时,通过 ObjectMessage.getObject() 反序列化其负载,且未设置 ObjectInputFilter、未使用类白名单或黑名单。因为当 mapJmsMessage=true(默认值)且 Camel 作为 JMS 消费者时,此方法总会被调用,所以攻击者若能向消费的队列/主题发布精心构造的 ObjectMessage,且类路径上存在利用链(gadget chain),则可实现远程代码执行。
安全公告: https://camel.apache.org/security/CVE-2026-40860.html
// JmsBinding.extractBodyFromJms(Exchange, Message) - 受影响版本
if (message instanceof ObjectMessage objectMessage) {
Object payload = objectMessage.getObject(); // <-- 未使用 ObjectInputFilter 进行反序列化
if (payload instanceof DefaultExchangeHolder holder) {
...
}
return payload;
}
getObject() 会在消息体上运行 JMS 提供者的 ObjectInputStream.readObject()。Camel 本身未添加任何类过滤,因此类路径上的利用链会在反序列化期间被执行。
修复版本(4.14.7 / 4.18.2 / 4.20.0)添加了一个默认的 ObjectInputFilter 白名单(java.**;javax.**;org.apache.camel.**;!*),可通过新的端点选项 deserializationFilter 或 JVM 全局的 -Djdk.serialFilter 进行自定义。注意 Camel 针对此修复的提交信息:
该检查在 JMS 提供者已经反序列化负载之后才运行。它可以防止意外类传播到路由,但无法阻止在提供者
ObjectInputStream内部通过readObject()触发的利用链。完全保护需要配置 JMS 提供者自身的反序列化过滤器和/或 JVM 全局的-Djdk.serialFilter。
因此,完全保护 = 升级 Camel + 限制提供者/JVM 过滤器。此 PoC 使用一个带有 trustAllPackages=true(常见的实际环境配置)的 ActiveMQ 客户端,以便提供者反序列化负载;在受影响的 Camel 版本上,没有其他阻碍。
from("jms:queue:evil") // mapJmsMessage 默认为 true
.log("Consumed: ${body.class.name}");
仅接收 ObjectMessage 就会触发反序列化——路由体内容无关紧要。
受害者是 Camel JMS 消费者。攻击者是任何能够向队列发布消息的生产者。两者都连接到一个在 Docker 中运行的真实的 Apache ActiveMQ Artemis 代理。
CVE-2026-40860/
├── pom.xml # camel-jms 4.18.1 + activemq-client 6.2.4 + commons-collections 3.2.1 (利用链)
├── Dockerfile # 运行应用(--add-opens 仅用于构建利用链)
├── docker-compose.yml # Artemis 代理 (quay.io) + 复现应用
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── JmsConfig.java # OpenWire ConnectionFactory (trustAllPackages=true) + jms 组件
│ ├── VictimRoute.java # 受害者: from("jms:queue:evil")
│ ├── Gadget.java # CommonsCollections6 利用链,在执行 getObject() 期间触发
│ └── ExploitController.java # 攻击者: 向队列发布 ObjectMessage(利用链)
└── resources/
└── application.properties
在实际攻击中,序列化字节由攻击者离线生成(例如使用 ysoserial);只有受害者需要类路径上的利用链。此 PoC 为了方便在进程内构建利用链,这就是 JVM 使用
--add-opens java.base/java.util=ALL-UNNAMED的原因——这是一个利用链构造细节,与漏洞无关。
mvn clean package -DskipTests
docker compose up -d --build
这会启动一个 Artemis 代理(quay.io/artemiscloud/activemq-artemis-broker)和复现应用,该应用通过 OpenWire 连接到它。
curl -s http://localhost:8080/exploit/attack
# -> ObjectMessage 已发布到队列 'evil'。
# camel-jms 消费者调用了 ObjectMessage.getObject() -> 反序列化。
#
# >>> RCE 证明 — /tmp/pwned 存在: true
docker exec cve-2026-40860 ls -la /tmp/pwned
docker compose down
任何配置为从攻击者可发布消息的目的地(共享代理、允许开放生产者主题、由不可信上游注入的队列)读取消息的 Camel JMS 消费者(camel-jms、camel-sjms、camel-sjms2、camel-amqp、camel-activemq、camel-activemq6),且 mapJmsMessage=true(默认值),均可能受影响。
mapJmsMessage=true(默认值)。ObjectMessage。trustAllPackages=true,或提供者未设置严格过滤器)。commons-collections:3.2.1)。升级至 4.14.7 / 4.18.2 / 4.20.0,并端到端地限制反序列化:
-Djdk.serialFilter=java.**;org.apache.camel.**;!*(或使用端点的新选项 deserializationFilter)。trustedPackages,不要使用 trustAllPackages=true)。在完成升级之前:
ObjectMessage 负载;在可接受原始消息时设置 mapJmsMessage=false。trustAllPackages=true。-Djdk.serialFilter。此复现工具仅供安全研究和授权测试使用,针对的是一个已公开披露并已修复的漏洞。未经明确许可,请勿将其用于任何系统。
| 属性 | 值 |
|---|
| 组件 | camel-jms (+ camel-sjms, camel-sjms2, camel-amqp, camel-activemq, camel-activemq6) |
| 受影响类 | org.apache.camel.component.jms.JmsBinding#extractBodyFromJms → jakarta.jms.ObjectMessage#getObject() |
| CWE | CWE-502: 不可信数据的反序列化 |
| 影响 | 远程代码执行 (RCE) |
| 触发条件 | Camel JMS 消费者 + mapJmsMessage=true(默认)+ 攻击者可入队的 ObjectMessage |
| 受影响版本 | 从 3.0.0 到 4.14.7 之前,从 4.15.0 到 4.18.2 之前,从 4.19.0 到 4.20.0 之前 |
| 修复版本 | 4.14.7, 4.18.2, 4.20.0 |
| JIRA | CAMEL-23321 |
| 报告者 | Venkatraman Kumar (Securin) |