Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-94386 — Reproducer eseguibile in Spring Boot e Quarkus per CVE-2026-94386, che dimostra il riutilizzo di token OAuth tra scope diversi nella cache statica dei token di camel-oauth di Apache Camel. | Kitploit
Strumenti/GitHubGitHub/oscerd/cve-2026-94386
Strumenti DifensiviAnalisi delle VulnerabilitàSicurezza WebAutenticazioneApprendimento e Formazione
GitHuboscerd/cve-2026-94386

CVE-2026-94386

Reproducer eseguibile in Spring Boot e Quarkus per CVE-2026-94386, che dimostra il riutilizzo di token OAuth tra scope diversi nella cache statica dei token di camel-oauth di Apache Camel.

Vedi Repository
43 giorni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2026-94386 — camel-oauth: riutilizzo di token tra scope diversi tramite una cache di token globale JVM con chiave insufficiente

PoC riproducibile ed eseguibile per la vulnerabilità di Apache Camel in cui OAuthClientCredentialsTokenResolver manteneva i token client-credentials ottenuti in una cache statica condivisa da ogni istanza del resolver e da ogni CamelContext nella JVM, e usava come chiave di tale cache solo l'endpoint del token e il client ID — sebbene la richiesta del token trasporti anche il client secret e lo scope richiesto.

// affected
record TokenCacheKey(String tokenEndpoint, String clientId) { }
RuntimeDirectoryStack
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)

Cosa dimostra

Due profili che condividono un token endpoint e un client ID ma richiedono scope diversi, oppure si autenticano con client secret diversi, mappati sulla stessa voce di cache. Il profilo che ha risolto per primo l'ha popolata; all'altro è stato poi consegnato quel token, senza che fosse effettuata alcuna richiesta di token con la propria configurazione, per tutto il tempo in cui il token è rimasto valido.

La cache dei token è attiva per impostazione predefinita, e indirizzare più profili verso un unico client di un identity provider è un uso ordinario del supporto ai profili, non un'adesione esplicita a un'impostazione non sicura.

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

Output su una build interessata (identico su entrambi i runtime):

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: ...

Il valore del token indica lo scope e il secret per cui è stato emesso, così puoi vedere da quale profilo proviene effettivamente la configurazione di ciascun token. Il log delle richieste alla fine è la prova concreta: con la cache attiva, all'identity provider non è mai stato chiesto il token del profilo admin — compaiono solo la richiesta del primo profilo e quella del controllo.

La sonda 2 utilizza deliberatamente una seconda istanza del resolver: la cache è static, quindi un'istanza separata — e un CamelContext separato — la condivide.

Chi è interessato

Il resolver ottiene i token per conto dei componenti che autenticano le proprie chiamate in uscita con un profilo OAuth denominato — camel-openai, camel-langchain4j-agent, camel-huggingface, camel-docling, camel-a2a, camel-spring-ai-chat e i componenti IBM watsonx — e delle applicazioni che chiamano direttamente la SPI OAuthClientAuthenticationFactory.

Raggiungere il problema richiede un deployment che definisca più di un profilo che condivide un token endpoint e un client ID ma differisce nello scope o nel client secret.

Modello di minaccia

I profili sono configurati dal deployment, che è considerato attendibile, quindi nessun input non attendibile raggiunge la cache. La parte che ne trae vantaggio è il servizio che riceve un token che non avrebbe dovuto ricevere, il quale, se ostile o compromesso, può riprodurre quel token entro il suo scope. Il risultato è una richiesta in uscita che trasporta un token emesso per lo scope di un altro profilo — un'autorità più ampia di quella per cui il profilo chiamante era configurato, oppure un servizio per cui il token non era stato emesso. Con identity provider che derivano l'audience di un token dallo scope richiesto, uno scope diverso può significare un token per un servizio completamente diverso.

Come è collegato

Nessun identity provider e nessuna rete. L'app ospita un sostituto del token endpoint del provider che serve il grant client-credentials, il quale emette un token il cui valore indica lo scope e il client secret per cui è stato emesso, e registra ogni richiesta. Vengono eseguiti il vero OAuthClientCredentialsTokenResolver e la vera cache statica.

Il sostituto legge le credenziali del client dall'header di autorizzazione HTTP Basic, non dai parametri del form, perché è così che camel-oauth le invia.

Riepilogo della vulnerabilità

ProprietàValore
Componentecamel-oauth (OAuthClientCredentialsTokenResolver)
CWECWE-524 (Use of Cache Containing Sensitive Information)
GravitàMedia
Vettore di attaccoDue o più profili OAuth che condividono un token endpoint e un client ID ma differiscono nello scope o nel client secret
ImpattoUna richiesta in uscita che trasporta un token emesso per lo scope di un altro profilo o ottenuto con il secret di un altro profilo
Versioni interessateDalla 4.19.0 precedenti alla 4.22.2
Versioni corrette4.22.2, 4.23.0
JIRACAMEL-24872
CreditoAndrea Cosentino della Apache Software Foundation

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

La correzione

La chiave della cache ora contiene ogni input della richiesta di token: il token endpoint, il client ID, un'impronta SHA-256 del client secret — così il secret in chiaro non viene conservato nella cache statica — e lo scope richiesto. Uno scope assente, vuoto o composto solo da spazi conta come un unico valore, poiché ciascuno di essi omette il parametro scope dalla richiesta; qualsiasi altro scope viene confrontato esattamente. I profili che concordano su tutti e quattro condividono ancora un token tra istanze del resolver, mentre i profili che differiscono nelle credenziali o nello scope ottengono token separati.

Corretto su main in apache/camel#26681 (5e896b2d), con backport su camel-4.22.x in #27779 (b2d9957b).

Verifica di una build corretta

Imposta camel.version su 4.22.2 ed eseguilo di nuovo. Verificato su 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

>>> NOT reproduced: each profile got a token for its own scope and secret.
Scarica lo strumento