
Lauffähiger Spring-Boot-Proof-of-Concept zur Reproduktion von CVE-2026-88900, der unsicheren Java-Deserialisierungs-Schwachstelle in camel-jgroups, der das Verhalten von betroffenen und gepatchten Versionen zeigt.
Lauffähiger Proof-of-Concept-Reproducer für die Apache-Camel-Schwachstelle, bei der der jgroups-Consumer
Cluster-Nachrichten ohne Filter Java-deserialisierte. JGroupsEndpoint.createExchange(Message) — aufgerufen für jede
Nachricht, die der Consumer empfängt — setzte den Exchange-Body aus org.jgroups.Message.getObject(). Bei einer ObjectMessage
(der Typ, den der Camel-jgroups-Producer sendet) Java-deserialisiert JGroups die Nutzlast über einen ObjectInputStream,
sobald die Nachricht eintrifft, und getObject() gibt das Ergebnis zurück. Es wurde kein java.io.ObjectInputFilter angewendet, sodass jede serialisierbare Klasse im Anwendungs-Classpath, die aus dem Cluster empfangen wurde, instanziiert und ihre Deserialisierungs-Callbacks ausgeführt wurden — Remote Code Execution, wenn eine nutzbare Gadget-Chain vorhanden ist. Mit dem Standard-new JChannel()-Stack
(UDP-Multicast, kein AUTH, keine Verschlüsselung) kann jeder Host, der den Cluster erreichen kann, eine solche Nachricht ohne
Anmeldedaten senden (CWE-502).
Nur Spring Boot. Dieser Reproducer enthält ein einzelnes Camel-Spring-Boot-Modul.
camel-jgroupshat keinecamel-quarkus-jgroups-Erweiterung, daher gibt es kein Quarkus-Pendant zur Reproduktion. Das Spring-Boot-Modul demonstriert das betroffene und das behobene Verhalten.
| Laufzeit | Verzeichnis | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-jgroups 4.22.0 (betroffen; behoben in 4.22.1) |
Ein harmloses Angreiferobjekt — com.example.Marker, eine gewöhnliche Anwendungsklasse, die nicht in der Standard-
Allow-List des Fixes (java.**, javax.**, org.apache.camel.**) enthalten ist — wird in die JGroups-Wire-Form serialisiert und an das
echte JGroupsEndpoint.createExchange(...) übergeben, das es mit Message.getObject() liest (derselbe Aufruf, den der Consumer
für jede empfangene Nachricht macht). Es wird kein Channel oder Multicast benötigt, sodass die Prüfung deterministisch ist. Marker.readObject
setzt ein Flag, um zu zeigen, dass der Deserialisierungs-Callback ausgeführt wird — eine echte Gadget-Chain würde an genau dieser Stelle
schädlichen Code ausführen; dieser Reproducer enthält kein Gadget.
com.example.Marker ab und createExchange wirft
JGroupsException; das Objekt erreicht die Route nie.Ehrlicher Vorbehalt (wie im Advisory angegeben): Die Klassenprüfung in 4.22.1 / 4.18.5 läuft nachdem JGroups die Nutzlast deserialisiert hat, sodass der
readObject-Callback auch im behobenen Build noch ausgeführt wird — es ist Defense-in-Depth. Um Code zu stoppen, der während der Deserialisierung läuft, müssen Sie zusätzlich einen JVM-weiten-Djdk.serialFiltersetzen und den Channel mitAUTH+ Verschlüsselung absichern; 4.23.0 verweigert zusätzlich den Start eines Consumers, sofern nicht eine dieser Kontrollen konfiguriert ist. Dieser Reproducer zeigt das Klassenprüfungs-Differential; das Callback-ausgeführt-Flag macht den Vorbehalt sichtbar.
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
| Eigenschaft | Wert |
|---|---|
| Komponente | camel-jgroups (JGroupsEndpoint.createExchange) |
| CWE | CWE-502 (Deserialisierung nicht vertrauenswürdiger Daten) |
| Schweregrad | HOCH |
| Angriffsvektor | Ein Host, der die Multicast-Gruppe bzw. den Bind-Port des Clusters erreichen kann, sendet eine manipulierte ObjectMessage; der Consumer deserialisiert sie ohne Filter |
| Auswirkung | Remote-Code-Ausführung im Camel-Prozess, wenn eine Gadget-Chain im Classpath vorhanden ist; andernfalls beliebige Klasseninstanziierung |
| Betroffene Versionen | Ab 4.0.0 vor 4.18.5, ab 4.19.0 vor 4.22.1 |
| Behobene Versionen | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24676, CAMEL-25223 |
| Gemeldet von | h1ei1 |
Advisory: https://camel.apache.org/security/CVE-2026-88900.html
JGroupsEndpoint prüft nun die Klasse des von
Message.getObject() zurückgegebenen Bodys, bevor der Exchange weitergeleitet wird, über eine neue Option
deserializationFilter (Syntax von jdk.serialFilter). Ist diese nicht gesetzt, wird ein JVM-weiter
jdk.serialFilter beachtet, sofern vorhanden; andernfalls erlaubt eine konservative Standard-Allow-List
java.**/javax.**/org.apache.camel.**, verweigert java.net.** und lehnt alles andere ab; eine
abgelehnte Nachricht wird an den ExceptionHandler des Consumers gemeldet und nicht weitergeleitet. In 4.23.0
(CAMEL-25223) verweigert der Consumer außerdem den Start, sofern keine Kontrolle konfiguriert ist, die
vor der Deserialisierung greift (ein JVM-weiter Filter, die System-Property jgroups.deserialization.filter
oder ein AUTH+Verschlüsselungs-Kanal). acceptAllObjects=true stellt das alte Verhalten wieder her und ist
als unsichere Einstellung gekennzeichnet.
Setzen Sie -Djdk.serialFilter auf der JVM, die den Consumer ausführt (wobei nur die Klassen zugelassen werden,
die Ihre Routen über den Cluster austauschen), sichern Sie den Kanal mit AUTH und SYM_ENCRYPT/ASYM_ENCRYPT
über die Option channelProperties ab und setzen Sie die Multicast-Gruppe bzw. den Bind-Port des Clusters nicht
unvertrauenswürdigen Netzwerken aus.
Dieses Repository wird zu Bildungs- und Verteidigungszwecken veröffentlicht: um Apache-Camel-Nutzern zu helfen, die Schwachstelle zu verstehen, zu prüfen, ob sie betroffen sind, und zu bestätigen, dass ein Upgrade sie behebt. Das deserialisierte Objekt ist eine harmlose Marker-Klasse, die in diesem Repository definiert ist; sie enthält keine Gadget-Chain und führt keine schädlichen Aktionen aus. Verwenden Sie dieses Material nicht gegen Systeme, die Ihnen nicht gehören oder die Sie nicht betreiben.