Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-94386 — Reproducteur exécutable Spring Boot et Quarkus pour CVE-2026-94386, démontrant la réutilisation de jetons OAuth entre portées dans le cache de jetons statique de camel-oauth d'Apache Camel. | Kitploit
Outils/GitHubGitHub/oscerd/cve-2026-94386
Outils DéfensifsAnalyse des VulnérabilitésSécurité WebAuthentificationApprentissage et Éducation
GitHuboscerd/cve-2026-94386

CVE-2026-94386

Reproducteur exécutable Spring Boot et Quarkus pour CVE-2026-94386, démontrant la réutilisation de jetons OAuth entre portées dans le cache de jetons statique de camel-oauth d'Apache Camel.

Voir le dépôt
6il y a 4 joursPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-94386 — camel-oauth : réutilisation de jetons entre portées via un cache de jetons global au JVM sous-clé

Reproducteur de preuve de concept exécutable pour la vulnérabilité Apache Camel où OAuthClientCredentialsTokenResolver conservait les jetons client-credentials qu'il obtenait dans un cache statique partagé par chaque instance de resolver et chaque CamelContext du JVM, et indexait ce cache sur le point de terminaison du jeton et l'ID client uniquement — bien que la requête de jeton transporte également le client secret et la portée demandée.

// affected
record TokenCacheKey(String tokenEndpoint, String clientId) { }
RuntimeRépertoireStack
Camel Spring Bootcamel-spring-boot/Spring Boot 3.5.13 + camel-oauth 4.22.1
Camel Quarkuscamel-quarkus/Camel Quarkus 3.39.0 (Quarkus 3.39.0, Camel 4.22.0)

Ce que cela démontre

Deux profils qui partagent un endpoint de jeton et un ID client mais demandent des scopes différents, ou s'authentifient avec des secrets client différents, mappés vers la même entrée de cache. Le profil résolu en premier l'a peuplée ; l'autre s'est ensuite vu remettre ce jeton, sans qu'aucune requête de jeton ne soit effectuée selon sa propre configuration, tant que le jeton restait valide.

La mise en cache des jetons est activée par défaut, et pointer plusieurs profils vers un même client de fournisseur d'identité est un usage ordinaire du support des profils plutôt qu'une adhésion à un paramètre non sécurisé.

cd camel-spring-boot          # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
until curl -sf http://localhost:8080/exploit/ready >/dev/null; do sleep 1; done
curl -s http://localhost:8080/exploit/attack
docker compose down

Sur une version affectée (identique sur les deux runtimes) :

1) Profile 'invoices' resolves first
     token handed to it: TOKEN-FOR[scope=invoice.read;secret=...aaaa]
     token requests the IdP has received: 1

2) Profile 'admin' resolves next, through a DIFFERENT resolver instance
     token handed to it: TOKEN-FOR[scope=invoice.read;secret=...aaaa]
     token requests the IdP has received: 1  (unchanged - no request was made under its own config)
     it was handed the token issued for the OTHER profile's scope: true

3) Profile 'partner' - same endpoint and clientId, DIFFERENT client secret (...-zzzz)
     token handed to it: TOKEN-FOR[scope=invoice.read;secret=...aaaa]
     it was served the token obtained with the other secret, without ever
     authenticating with its own: true

4) CONTROL - profile 'admin' again with cache-tokens=false
     token handed to it: TOKEN-FOR[scope=admin.write;secret=...aaaa]
     it got a token for its own scope: true

Everything the IdP was actually asked for:
  - client_id=camel-integration-client scope=invoice.read;secret=...aaaa
  - client_id=camel-integration-client scope=admin.write;secret=...aaaa

>>> PROVEN: ...

La valeur du jeton nomme la portée et le secret pour lesquels il a été émis, ce qui vous permet de voir de quel profil provient réellement la configuration de chaque jeton. Le journal des requêtes à la fin constitue la preuve irréfutable : avec la mise en cache activée, le fournisseur d'identité n'a jamais été sollicité pour le jeton du profil admin — seules la requête du premier profil et celle du contrôle apparaissent.

La sonde 2 utilise délibérément une seconde instance de resolver : le cache est static, donc une instance distincte — et un CamelContext distinct — le partagent.

Qui est affecté

Le resolver obtient des jetons pour le compte des composants qui authentifient leurs appels sortants avec un profil OAuth nommé — camel-openai, camel-langchain4j-agent, camel-huggingface, camel-docling, camel-a2a, camel-spring-ai-chat et les composants IBM watsonx — ainsi que des applications appelant directement le SPI OAuthClientAuthenticationFactory.

Atteindre le problème nécessite un déploiement qui définit plusieurs profils partageant un endpoint de jeton et un ID client tout en différant par la portée ou le secret client.

Modèle de menace

Les profils sont configurés par le déploiement, qui est de confiance, donc aucune entrée non fiable n'atteint le cache. La partie qui en bénéficie est le service qui reçoit un jeton qu'il n'était pas censé recevoir, lequel, s'il est hostile ou compromis, peut rejouer ce jeton dans sa portée. Le résultat est une requête sortante portant un jeton émis pour la portée d'un autre profil — une autorité plus large que celle pour laquelle le profil appelant était configuré, ou un service pour lequel le jeton n'a pas été émis. Avec des fournisseurs d'identité qui dérivent l'audience d'un jeton à partir de la portée demandée, une portée différente peut signifier un jeton pour un service entièrement différent.

Comment c'est câblé

Aucun fournisseur d'identité et aucun réseau. L'application héberge un substitut de l'endpoint de jeton du fournisseur servant le grant client-credentials, qui émet un jeton dont la valeur nomme la portée et le secret client pour lesquels il a été émis, et enregistre chaque requête. Le véritable OAuthClientCredentialsTokenResolver et le véritable cache statique s'exécutent.

Le substitut lit les identifiants client depuis l'en-tête d'autorisation HTTP Basic, et non depuis les paramètres de formulaire, car c'est ainsi que camel-oauth les envoie.

Résumé de la vulnérabilité

PropriétéValeur
Composantcamel-oauth (OAuthClientCredentialsTokenResolver)
CWECWE-524 (Utilisation d'un cache contenant des informations sensibles)
GravitéMoyenne
Vecteur d'attaqueDeux profils OAuth ou plus partageant un endpoint de jeton et un ID client tout en différant par la portée ou le secret client
ImpactUne requête sortante portant un jeton émis pour la portée d'un autre profil ou obtenu avec le secret d'un autre profil
Versions affectéesÀ partir de 4.19.0 avant 4.22.2
Versions corrigées4.22.2, 4.23.0
JIRACAMEL-24872
CréditAndrea Cosentino de l'Apache Software Foundation

Avis : https://camel.apache.org/security/CVE-2026-94386.html

Le correctif

La clé de cache contient désormais chaque entrée de la requête de jeton : l'endpoint de jeton, l'ID client, une empreinte SHA-256 du secret client — afin que le secret brut ne soit pas conservé dans le cache statique — et la portée demandée. Une portée absente, vide ou blanche compte comme une seule valeur, car chacune d'elles omet le paramètre scope de la requête ; toute autre portée est mise en correspondance exacte. Les profils qui concordent sur les quatre partagent toujours un jeton entre les instances de resolver, tandis que les profils qui diffèrent par les identifiants ou la portée obtiennent des jetons distincts.

Corrigé sur main dans apache/camel#26681 (5e896b2d), rétroporté vers camel-4.22.x dans #27779 (b2d9957b).

Vérification d'une version corrigée

Définissez camel.version sur 4.22.2 et exécutez-le à nouveau. Vérifié sur 4.22.1 → 4.22.2 :

2) Profile 'admin' resolves next, through a DIFFERENT resolver instance
     token handed to it: TOKEN-FOR[scope=admin.write;secret=...aaaa]
     token requests the IdP has received: 2
     it was handed the token issued for the OTHER profile's scope: false

3) Profile 'partner' ... token handed to it: TOKEN-FOR[scope=invoice.read;secret=...zzzz]
     it was served the token obtained with the other secret ...: false
Télécharger l’outil