针对 Apache Camel 漏洞的可运行概念验证复现程序:camel-hazelcast 在两条配置路径上创建 Hazelcast 实例时未配置 JavaSerializationFilterConfig,而 CVE-2026-43865 的加固措施从未覆盖这两条路径。在这些路径上,由 Camel 构建的 Hazelcast 成员/客户端在反序列化从集群读取的值时没有任何类限制,因此能够向集群发布数据的攻击者可以使其选定的序列化 Java 对象在 Hazelcast 的序列化层内被反序列化——从而实现远程代码执行(CWE-502)。Hazelcast 集群默认既未启用身份验证,也未启用 TLS。
本复现程序针对两条路径中最清晰的一条:ReplicatedHazelcastAggregationRepository,它重写了 doStart() 却没有调用 super.doStart(),并且在受影响的构建版本上,启动自己的本地成员时未应用默认过滤器。(另一条同类路径 HazelcastDefaultComponent#getOrCreateHzClientInstance()(用于 hazelcastMode=client)由同一修复覆盖。)
| 运行时 | 目录 | 技术栈 |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-hazelcast 4.22.0(受影响;已在 4.22.1 中修复) |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.29.0 + camel-quarkus-hazelcast 3.29.0(Camel 4.15.0,受影响) |
修复版与受影响版对照: 修复随 Camel 4.18.5 / 4.22.1 / 4.23.0 发布。Spring Boot 模块可以同时运行受影响构建(4.22.0)和修复后构建(4.22.1),因此它也能演示已修补的行为。目前尚无已发布的 Camel Quarkus 捆绑修复后的 Camel(最新的 3.29.0 仍基于 Camel 4.15.0),因此 Quarkus 模块仅演示受影响的情况。
该应用运行一条由 ReplicatedHazelcastAggregationRepository 支撑的 Camel 路由,且未从外部提供 HazelcastInstance,因此该仓库会启动自己的本地 Hazelcast 成员(默认集群 dev,端口 5701)。在受影响的构建上,该成员没有 JavaSerializationFilterConfig。
随后,一个攻击者客户端加入集群,并向底层 ReplicatedMap 发布一个序列化对象。Hazelcast 客户端只发送字节——它不存储也不反序列化映射值——因此任何触发的反序列化都可归因于受害成员。所发布的对象是一个刻意设计的良性标记 com.example.PwnMarker:它不携带任何 gadget 链,也不执行任何命令,仅(通过 JVM 全局标志)记录其 readObject 已执行。真实攻击者会在此处发布已知的 gadget 类以实现 RCE——证明该类确实被反序列化就已足够。
由于修复引入的默认过滤器是 java.、javax. 和 org.apache.camel. 类名前缀的白名单,com.example.PwnMarker 是完美的判定依据:
PwnMarker 被反序列化,readObject 在受害成员上执行 → 已证实。readObject 之前拒绝 com.example.PwnMarker → java.lang.SecurityException: Resolving class com.example.PwnMarker is not allowed → 未被利用。cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
在受影响的构建版本上预期输出:
=== CVE-2026-78162 — camel-hazelcast ReplicatedHazelcastAggregationRepository ===
=== missing JavaSerializationFilterConfig on the Camel-built member ===
Attacker client joined the victim cluster 'dev' at 127.0.0.1:5701.
Attacker published a com.example.PwnMarker into ReplicatedMap 'aggregation'.
Result:
>>> PROVEN: the Camel-built Hazelcast member deserialized an attacker-supplied, non-whitelisted
>>> class (com.example.PwnMarker) with no JavaSerializationFilterConfig in effect — its readObject
>>> executed inside the victim. A real attacker would publish a gadget class here instead, for RCE.
>>> PwnMarker.readObject executed inside the victim member; tag=attacker-rce-marker; thread=hz.*.partition-operation.thread-1
| 属性 | 值 |
|---|---|
| 组件 | camel-hazelcast(camel-hazelcast-starter / camel-quarkus-hazelcast) |
| CWE | CWE-502(不可信数据的反序列化) |
| 严重程度 | 中危 |
| 攻击向量 | 能够向受影响实例所连接的 Hazelcast 集群发布数据的攻击者;由 Camel 构建的成员/客户端在无类限制的情况下反序列化所发布的对象 |
| 影响 | 在 Camel 处理交换之前,于 Camel 进程内实现远程代码执行(通过 gadget 类) |
| 受影响版本 | 从 4.0.0 起至 4.18.5 之前,从 4.19.0 起至 4.22.1 之前 |
| 修复版本 | 4.18.5、4.22.1、4.23.0 |
| JIRA | CAMEL-24413、CAMEL-24420 |
| 致谢 | 来自 TCBS 的 cattier;Leon Zlobecki |
公告:https://camel.apache.org/security/CVE-2026-78162.html
HazelcastSerializationFilterHelper.applyDefault(...) 新增了一个 ClientConfig 重载,并且现在会在两条此前未被覆盖的路径上被调用——ReplicatedHazelcastAggregationRepository#doStart() 和 HazelcastDefaultComponent#getOrCreateHzClientInstance()——因此 Camel 自行构建的每个 Hazelcast 配置都会携带默认的 JavaSerializationFilterConfig(白名单 java. / javax. / org.apache.camel.,黑名单 java.net.)。用户提供的 Config、ClientConfig 或 HazelcastInstance 仍然保持原样、不被修改。本公告是针对 CVE-2026-43865 的不完整修复后续公告。
提供一个显式携带 JavaSerializationFilterConfig 的 Hazelcast 配置,或注入一个预先构建的 HazelcastInstance(Camel 绝不会覆盖用户提供的配置);设置 JVM 级别的 -Djdk.serialFilter=...;并启用 Hazelcast 集群认证和 TLS。
本仓库的发布出于教育和防御目的:帮助 Apache Camel 用户理解该漏洞、验证自身是否受影响,并确认升级能够解决该问题。该载荷是一个良性标记,不会执行任何代码。请勿将本材料用于您不拥有或运营的系统。