
Prueba de concepto ejecutable de Spring Boot que reproduce CVE-2026-88900, la vulnerabilidad de deserialización Java insegura de camel-jgroups, mostrando el comportamiento afectado frente al parcheado.
Reproductor de prueba de concepto ejecutable para la vulnerabilidad de Apache Camel en la que el consumidor de jgroups
deserializaba en Java los mensajes del clúster sin ningún filtro. JGroupsEndpoint.createExchange(Message) — invocado para cada
mensaje que recibe el consumidor — establecía el cuerpo del exchange a partir de org.jgroups.Message.getObject(). Para un ObjectMessage
(el tipo que envía el productor de jgroups de Camel), JGroups deserializa en Java el payload mediante un ObjectInputStream a medida que
llega el mensaje, y getObject() devuelve el resultado. No se aplicaba ningún java.io.ObjectInputFilter, por lo que cualquier
clase serializable del classpath de la aplicación recibida desde el clúster era instanciada y se ejecutaban sus callbacks de
deserialización — ejecución remota de código cuando hay disponible una cadena de gadgets utilizable. Con la pila estándar de new JChannel()
(multicast UDP, sin AUTH, sin cifrado), cualquier host que pueda alcanzar el clúster puede enviar dicho mensaje sin
credenciales (CWE-502).
Solo Spring Boot. Este reproductor incluye un único módulo Camel Spring Boot.
camel-jgroupsno tiene una extensióncamel-quarkus-jgroups, por lo que no hay una contraparte Quarkus que reproducir. El módulo Spring Boot demuestra el comportamiento afectado y el corregido.
| Runtime | Directorio | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-jgroups 4.22.0 (afectado; corregido en 4.22.1) |
Un objeto atacante benigno — com.example.Marker, una clase de aplicación ordinaria que no está en la lista de
permitidos por defecto de la corrección (java.**, javax.**, org.apache.camel.**) — se serializa al formato de transmisión de JGroups y se pasa al
JGroupsEndpoint.createExchange(...) real, que lo lee con Message.getObject() (la misma llamada que hace el consumidor
para cada mensaje recibido). No se necesita ningún canal ni multicast, por lo que la comprobación es determinista. Marker.readObject
activa un flag para mostrar que el callback de deserialización se ejecuta — una cadena de gadgets real ejecutaría código dañino en ese mismo
punto; este reproductor no contiene ningún gadget.
com.example.Marker y createExchange lanza
JGroupsException; el objeto nunca llega a la ruta.Advertencia honesta (como indica el aviso): la comprobación de clases de 4.22.1 / 4.18.5 se ejecuta después de que JGroups haya deserializado el payload, por lo que el callback
readObjectsigue ejecutándose también en la compilación corregida — es defensa en profundidad. Para detener el código que se ejecuta durante la deserialización también debe establecer un-Djdk.serialFiltera nivel de JVM y proteger el canal conAUTH+ cifrado; 4.23.0 además se niega a iniciar un consumidor a menos que uno de esos controles esté configurado. Este reproductor muestra el diferencial de la comprobación de clases; el flag de callback ejecutado hace visible la advertencia.
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
| Propiedad | Valor |
|---|---|
| Componente | camel-jgroups (JGroupsEndpoint.createExchange) |
| CWE | CWE-502 (Deserialización de datos no confiables) |
| Severidad | ALTA |
| Vector de ataque | Un host que pueda alcanzar el grupo multicast / puerto de enlace del clúster envía un ObjectMessage manipulado; el consumidor lo deserializa sin ningún filtro |
| Impacto | Ejecución remota de código en el proceso de Camel cuando hay una cadena de gadgets en el classpath; en caso contrario, instanciación arbitraria de clases |
| Versiones afectadas | Desde 4.0.0 anterior a 4.18.5, desde 4.19.0 anterior a 4.22.1 |
| Versiones corregidas | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24676, CAMEL-25223 |
| Reportado por | h1ei1 |
Aviso: https://camel.apache.org/security/CVE-2026-88900.html
JGroupsEndpoint ahora comprueba la clase del cuerpo devuelto por
Message.getObject() antes de que se enrute el exchange, mediante una nueva opción deserializationFilter (sintaxis
jdk.serialFilter). Cuando no está establecida, se respeta un jdk.serialFilter de ámbito JVM si está presente; en caso
contrario, una lista de permitidos predeterminada y conservadora permite java.**/javax.**/org.apache.camel.**,
deniega java.net.** y rechaza todo lo demás; un mensaje rechazado se notifica al ExceptionHandler del consumidor y
no se enruta. En 4.23.0 (CAMEL-25223) el consumidor también se niega a arrancar a menos que se configure un control
que actúe antes de la deserialización (un filtro de ámbito JVM, la propiedad del sistema jgroups.deserialization.filter,
o un canal AUTH+cifrado). acceptAllObjects=true restaura el comportamiento anterior y se marca como una
configuración insegura.
Establezca -Djdk.serialFilter en la JVM que ejecuta el consumidor (permitiendo solo las clases que sus rutas
intercambian a través del clúster), proteja el canal con AUTH y SYM_ENCRYPT/ASYM_ENCRYPT mediante la opción
channelProperties, y no exponga el grupo multicast ni el puerto de enlace del clúster a redes no confiables.
Este repositorio se publica con fines educativos y defensivos: para ayudar a los usuarios de Apache Camel a comprender la vulnerabilidad, verificar si se ven afectados y confirmar que la actualización la resuelve. El objeto deserializado es una clase marcadora benigna definida en este repositorio; no contiene ninguna cadena de gadgets y no realiza ninguna acción dañina. No utilice este material contra sistemas que no sean de su propiedad o que no opere.