
نموذج إثبات مفهوم قابل للتشغيل بـ Spring Boot يعيد إنتاج CVE-2026-88900، وهو ثغرة إزالة تسلسل Java غير الآمنة في camel-jgroups، ويُظهر السلوك المتأثر مقابل السلوك المُرقَّع.
مُعيد إنتاج قابل للتشغيل لإثبات المفهوم لثغرة Apache Camel حيث كانت مستهلك jgroups
يزيل تسلسل رسائل العنقود بتسلسل Java دون أي مُرشِّح. JGroupsEndpoint.createExchange(Message) — الذي يُستدعى لكل
رسالة يتلقاها المستهلك — كان يضبط جسم التبادل من org.jgroups.Message.getObject(). بالنسبة لـ ObjectMessage
(النوع الذي يرسله منتج Camel jgroups)، تقوم JGroups بإزالة تسلسل Java للحِمل عبر ObjectInputStream عند
وصول الرسالة، ويُعيد getObject() النتيجة. لم يُطبَّق أي java.io.ObjectInputFilter، لذا فإن أي صنف قابل للتسلسل
على مسار أصناف التطبيق يُستقبل من العنقود كان يُنشأ وتُنفَّذ عمليات استدعاء إزالة التسلسل الخاصة به — ما يؤدي إلى تنفيذ
شيفرة عن بُعد عند وجود سلسلة أدوات (gadget chain) قابلة للاستخدام. مع حزمة new JChannel() الافتراضية
(UDP multicast، بلا AUTH، بلا تشفير)، يمكن لأي مضيف يستطيع الوصول إلى العنقود إرسال مثل هذه الرسالة دون
بيانات اعتماد (CWE-502).
Spring Boot فقط. يُوفِّر مُعيد الإنتاج هذا وحدة Camel Spring Boot واحدة. لا يمتلك
camel-jgroupsامتدادcamel-quarkus-jgroups، لذا لا يوجد نظير في Quarkus لإعادة إنتاجه. تُوضِّح وحدة Spring Boot السلوك المُتأثِّر والمُصلَح معًا.
| بيئة التشغيل | الدليل | الحزمة |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-jgroups 4.22.0 (متأثرة؛ مُصلَحة في 4.22.1) |
كائن مهاجم غير ضار — com.example.Marker، وهو صنف تطبيق عادي ليس ضمن قائمة السماح الافتراضية
للإصلاح (java.**، javax.**، org.apache.camel.**) — يُسلسَل إلى صيغة JGroups السلكية ويُغذَّى إلى
JGroupsEndpoint.createExchange(...) الحقيقي، الذي يقرأه عبر Message.getObject() (نفس الاستدعاء الذي يُجريه المستهلك
لكل رسالة مُستقبَلة). لا حاجة إلى قناة أو بث متعدد (multicast)، لذا فإن الفحص حتمي. يقوم Marker.readObject
بقلب راية لإظهار أن استدعاء إزالة التسلسل يعمل — سلسلة أدوات حقيقية كانت ستنفِّذ شيفرة ضارة عند تلك النقطة
بالضبط؛ لا يحتوي مُعيد الإنتاج هذا على أي أداة (gadget).
com.example.Marker ويُطلق createExchange
استثناء JGroupsException؛ ولا يصل الكائن إلى المسار أبدًا.تحفُّظ صادق (كما ينص الاستشارة): يجري فحص الأصناف في 4.22.1 / 4.18.5 بعد أن تكون JGroups قد أزالت تسلسل الحِمل، لذا فإن استدعاء
readObjectلا يزال يعمل في البناء المُصلَح أيضًا — إنه دفاع متعدد الطبقات. لإيقاف الشيفرة التي تعمل أثناء إزالة التسلسل يجب أيضًا ضبط-Djdk.serialFilterعلى مستوى JVM وتأمين القناة باستخدامAUTH+ التشفير؛ كما أن 4.23.0 يرفض إضافيًا بدء مستهلك ما لم يُضبَط أحد تلك الضوابط. يُظهر مُعيد الإنتاج هذا فرق فحص الأصناف؛ وتُبرِز راية تشغيل الاستدعاء هذا التحفُّظ.
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected: Marker deserialized + routed; >>> PROVEN
docker compose down
# Patched control
mvn clean package -Dcamel.version=4.22.1
java -jar target/cve-2026-88900-jgroups-deserialization-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack # fixed: JGroupsException rejects com.example.Marker; >>> Not exploited
| الخاصية | القيمة |
|---|---|
| المكوّن | camel-jgroups (JGroupsEndpoint.createExchange) |
| CWE | CWE-502 (إلغاء تسلسل البيانات غير الموثوقة) |
| الخطورة | عالية |
| ناقل الهجوم | مضيف قادر على الوصول إلى مجموعة البث المتعدد (multicast group) الخاصة بالعنقود أو منفذ الربط يرسل ObjectMessage مصمّمة؛ يقوم المستهلك بإلغاء تسلسلها دون أي مرشّح |
| التأثير | تنفيذ شيفرة عن بُعد في عملية Camel عند وجود سلسلة أدوات (gadget chain) على مسار الفئات (classpath)؛ وإنشاء كائنات فئات عشوائية في الحالات الأخرى |
| الإصدارات المتأثرة | من 4.0.0 قبل 4.18.5، ومن 4.19.0 قبل 4.22.1 |
| الإصدارات المُصلحة | 4.18.5، 4.22.1، 4.23.0 |
| JIRA | CAMEL-24676، CAMEL-25223 |
| أبلغ عنه | h1ei1 |
الإشعار الأمني: https://camel.apache.org/security/CVE-2026-88900.html
أصبح JGroupsEndpoint يتحقق من فئة الجسم الذي يُرجعه
Message.getObject() قبل توجيه التبادل (exchange)، وذلك عبر خيار جديد deserializationFilter (بصيغة
jdk.serialFilter). وعندما لا يكون مضبوطًا، يُحترم jdk.serialFilter على مستوى JVM إن وُجد، وإلا فإن قائمة سماح
افتراضية متحفظة تسمح بـ java.**/javax.**/org.apache.camel.**، وتمنع java.net.** وترفض كل ما عدا ذلك؛
وتُبلَّغ الرسالة المرفوضة إلى ExceptionHandler الخاص بالمستهلك ولا تُوجَّه. وفي 4.23.0 (CAMEL-25223) يرفض
المستهلك أيضًا بدء التشغيل ما لم يُضبط ضابط يعمل قبل إلغاء التسلسل (مرشّح على مستوى JVM، أو خاصية النظام
jgroups.deserialization.filter، أو قناة AUTH+تشفير). ويعيد acceptAllObjects=true السلوك القديم ويُعدّ
إعدادًا غير آمن.
اضبط -Djdk.serialFilter على JVM التي تشغّل المستهلك (مع السماح فقط بالفئات التي تتبادلها مساراتك عبر
العنقود)، وأمّن القناة باستخدام AUTH وSYM_ENCRYPT/ASYM_ENCRYPT عبر خيار channelProperties، ولا تعرّض
مجموعة البث المتعدد الخاصة بالعنقود أو منفذ الربط لشبكات غير موثوقة.
يُنشر هذا المستودع لأغراض تعليمية ودفاعية: لمساعدة مستخدمي Apache Camel على فهم الثغرة، والتحقق مما إذا كانوا متأثرين بها، وتأكيد أن الترقية تحلّها. الكائن المُلغى تسلسله هو فئة علامة (marker class) غير ضارة معرّفة في هذا المستودع؛ ولا يحتوي على سلسلة أدوات ولا ينفّذ أي إجراء ضار. لا تستخدم هذه المواد ضد أنظمة لا تملكها أو لا تديرها.