
PoC riproducibile ed eseguibile per CVE-2026-85312, che dimostra il dirottamento della saga di Apache Camel tramite l'header Long-Running-Action in Spring Boot e Quarkus.
Long-Running-ActionRiproduttore proof-of-concept eseguibile per la vulnerabilità di Apache Camel in cui il SagaProcessor di camel-core selezionava il
coordinatore della saga dall'header del messaggio Long-Running-Action su ogni exchange. Quel nome di header non porta alcun
prefisso Camel, quindi si colloca al di fuori del namespace che i filtri degli header dei consumer rimuovono — un mittente esterno poteva fornirlo
su un messaggio in ingresso e quindi nominare la saga a cui il suo exchange si unisce, collegando la propria richiesta a una long-running
action avviata da qualcun altro (o associando una compensazione a un'azione che non ha iniziato). L'esposizione è
limitata ai deployment che eseguono saghe, ma dove si applica il mittente controlla a quale saga appartiene un exchange
(CWE-20).
| Runtime | Directory | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-spring-boot 4.22.0 (affetto; corretto in 4.22.1) |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.39.0 + camel-quarkus-saga (Camel 4.22.0, affetto; controllo corretto CQ 3.40.0 / Camel 4.22.1) |
Entrambi i moduli dimostrano il comportamento affetto e quello corretto rispetto al reale SagaProcessor di camel-core.
Il driver rispecchia il test di regressione della correzione stessa (SagaHeaderCannotSelectCoordinatorTest). Costruisce una route saga
from("direct:…").saga().propagation(MANDATORY) supportata da un servizio saga in memoria che registra ogni id di cui gli viene
richiesta la risoluzione, quindi invia un exchange che trasporta l'header in ingresso Long-Running-Action = a-saga-id-from-the-wire
— l'id che un mittente esterno collocherebbe sul filo. L'oracolo è semplicemente quali id di saga raggiungono il servizio:
a-saga-id-from-the-wire viene cercato
— il messaggio ha scelto il coordinatore.In entrambe le build l'exchange MANDATORY alla fine fallisce (non c'è una saga reale a cui unirsi) — la vulnerabilità non è il
fallimento ma il fatto che un id scelto dall'attaccante sia stato usato per selezionare il coordinatore, motivo per cui l'oracolo osserva la
ricerca anziché l'esito.
# Camel Spring Boot
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected: wire id looked up = true; >>> PROVEN
docker compose down
# Patched control
mvn clean package -Dcamel.version=4.22.1
java -jar target/cve-2026-85312-saga-header-hijack-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack # fixed: wire id looked up = false; >>> Not exploited
# Camel Quarkus
cd camel-quarkus
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected (Camel 4.22.0): wire id looked up = true
docker compose down
# Patched control: CQ 3.40.0 ships Camel 4.22.1
mvn clean package -Dcamel-quarkus.version=3.40.0 -Dquarkus.platform.version=3.40.0
java -jar target/quarkus-app/quarkus-run.jar &
curl -s http://localhost:8080/exploit/attack # fixed: wire id looked up = false
| Proprietà | Valore |
|---|---|
| Componente | camel-core (SagaProcessor.getCurrentSagaCoordinator) |
| CWE | CWE-20 (Validazione dell'input non corretta) |
| Gravità | MEDIA |
| Vettore di attacco | Un mittente esterno fornisce l'header Long-Running-Action senza prefisso su un messaggio in ingresso verso una route che esegue la saga EIP |
| Impatto | Il mittente indica la saga a cui si unisce uno scambio — collegandosi all'azione di lunga durata di un'altra parte, oppure associando erroneamente la compensazione |
| Versioni interessate | Dalla 4.0.0 precedente alla 4.18.5, dalla 4.19.0 precedente alla 4.22.1 |
| Versioni corrette | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24449 |
| Credito | Claude Security Scan Tool |
Advisory: https://camel.apache.org/security/CVE-2026-85312.html
Il modulo Quarkus interessato è basato su CQ 3.39.0 (Camel 4.22.0). Il controllo corretto è in CQ 3.40.0 (Camel 4.22.1).
SagaProcessor ora consulta l'header Long-Running-Action solo quando
il servizio saga dichiara di partecipare a tale protocollo, tramite il nuovo
CamelSagaService.isLongRunningActionHeaderSupported() (predefinito false; il servizio LRA lo sovrascrive a true). Lo
stato interno dello scambio — che sopravvive a removeHeaders("*") — rimane il normale veicolo dell'id della saga, quindi un messaggio
non può più scegliere il coordinatore per un servizio che non esegue alcun coordinatore esterno.
Rimuovere l'header al confine di fiducia con removeHeaders("Long-Running-Action") su ogni consumer che accetta
messaggi da un mittente non attendibile.
Questo repository è pubblicato per scopi educativi e difensivi: per aiutare gli utenti di Apache Camel a comprendere la vulnerabilità, verificare se sono interessati e confermare che l'aggiornamento la risolve. La dimostrazione esegue una route saga in-process con un servizio saga in memoria; l'id della saga dell'"attaccante" è una stringa segnaposto innocua. Non utilizzare questo materiale contro sistemi di cui non si è proprietari o gestori.