
Reproducteur de preuve de concept exécutable pour CVE-2026-78162, démontrant une désérialisation Java non authentifiée dans Apache Camel camel-hazelcast sur Spring Boot et Quarkus.
Reproducteur de preuve de concept exécutable pour la vulnérabilité Apache Camel où camel-hazelcast créait des instances Hazelcast sans JavaSerializationFilterConfig sur deux chemins de configuration que le durcissement de CVE-2026-43865 n'avait jamais atteints. Sur ces chemins, un membre/client Hazelcast construit par Camel désérialise les valeurs lues depuis le cluster sans aucune restriction de classe, de sorte qu'un attaquant capable de publier dans le cluster peut faire désérialiser un objet Java sérialisé de son choix à l'intérieur de la couche de sérialisation de Hazelcast — exécution de code à distance (CWE-502). Les clusters Hazelcast n'ont par défaut ni authentification ni TLS activés.
Ce reproducteur emprunte le plus clair des deux chemins : ReplicatedHazelcastAggregationRepository, qui redéfinit doStart() sans appeler super.doStart() et, sur une version affectée, démarre son propre membre local sans appliquer le filtre par défaut. (Le chemin frère, HazelcastDefaultComponent#getOrCreateHzClientInstance() pour hazelcastMode=client, est couvert par le même correctif.)
| Runtime | Répertoire | Pile |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-hazelcast 4.22.0 (affecté ; corrigé en 4.22.1) |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.29.0 + camel-quarkus-hazelcast 3.29.0 (Camel 4.15.0, affecté) |
Contrôle corrigé-vs-affecté : le correctif est livré dans Camel 4.18.5 / 4.22.1 / 4.23.0. Le module Spring Boot peut exécuter à la fois la version affectée (4.22.0) et la version corrigée (4.22.1), ce qui lui permet de démontrer également le comportement corrigé. Aucune version publiée de Camel Quarkus n'embarque encore un Camel corrigé (la dernière, 3.29.0, repose sur Camel 4.15.0), donc le module Quarkus ne démontre que le cas affecté.
L'application exécute une route Camel adossée à un ReplicatedHazelcastAggregationRepository sans HazelcastInstance fourni de l'extérieur, de sorte que le dépôt démarre son propre membre Hazelcast local (cluster par défaut dev, port 5701). Sur la version affectée, ce membre n'a pas de JavaSerializationFilterConfig.
Un client attaquant rejoint ensuite le cluster et publie un objet sérialisé dans la ReplicatedMap sous-jacente. Un client Hazelcast ne fait qu'envoyer des octets — il ne stocke ni ne désérialise les valeurs de la map — donc toute désérialisation qui se déclenche est attribuable au membre victime. L'objet publié est un marqueur délibérément bénin, com.example.PwnMarker : il ne porte aucune chaîne de gadgets et n'exécute aucune commande, il enregistre seulement (via un indicateur global à la JVM) que son readObject s'est exécuté. Un véritable attaquant publierait ici une classe de gadget connue, pour obtenir une RCE — prouver que la classe a bien été désérialisée suffit.
Comme le filtre par défaut du correctif est une liste blanche des préfixes de noms de classes java., javax. et org.apache.camel., com.example.PwnMarker est l'oracle parfait :
PwnMarker est désérialisé, readObject s'exécute sur le membre victime → PROUVÉ.com.example.PwnMarker avant readObject → java.lang.SecurityException: Resolving class com.example.PwnMarker is not allowed → non exploité.cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
Sortie attendue sur une version affectée :
=== 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
| Propriété | Valeur |
|---|---|
| Composant | camel-hazelcast (camel-hazelcast-starter / camel-quarkus-hazelcast) |
| CWE | CWE-502 (Désérialisation de données non fiables) |
| Gravité | MOYENNE |
| Vecteur d'attaque | Un attaquant capable de publier dans le cluster Hazelcast auquel une instance affectée est rattachée ; le membre/client construit par Camel désérialise l'objet publié sans aucune restriction de classe |
| Impact | Exécution de code à distance au sein du processus Camel (via une classe gadget), avant que Camel ne traite l'échange |
| Versions affectées | À partir de 4.0.0 avant 4.18.5, à partir de 4.19.0 avant 4.22.1 |
| Versions corrigées | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24413, CAMEL-24420 |
| Crédit | cattier de TCBS ; Leon Zlobecki |
Avis de sécurité : https://camel.apache.org/security/CVE-2026-78162.html
HazelcastSerializationFilterHelper.applyDefault(...) a gagné une surcharge ClientConfig et est désormais appelée sur les deux
chemins auparavant non couverts — ReplicatedHazelcastAggregationRepository#doStart() et
HazelcastDefaultComponent#getOrCreateHzClientInstance() — de sorte que toute configuration Hazelcast que Camel construit lui-même
porte le JavaSerializationFilterConfig par défaut (liste blanche java. / javax. / org.apache.camel., liste noire
java.net.). Un Config, ClientConfig ou HazelcastInstance fourni par l'utilisateur reste inchangé. Cet avis
est un suivi de correctif incomplet de CVE-2026-43865.
Fournissez une configuration Hazelcast explicite portant un JavaSerializationFilterConfig, ou injectez un
HazelcastInstance préconstruit (une configuration fournie par l'utilisateur n'est jamais écrasée par Camel) ; définissez la propriété JVM globale
-Djdk.serialFilter=... ; et activez l'authentification et TLS du cluster Hazelcast.
Ce dépôt est publié à des fins éducatives et défensives : pour aider les utilisateurs d'Apache Camel à comprendre la vulnérabilité, vérifier s'ils sont affectés, et confirmer que la mise à jour la résout. La charge utile est un marqueur bénin qui n'exécute aucun code. N'utilisez pas ce matériel contre des systèmes que vous ne possédez pas ou n'exploitez pas.