
CVE-2026-85312에 대한 실행 가능한 개념 증명 재현기로, Spring Boot와 Quarkus에서 Long-Running-Action 헤더를 통한 Apache Camel saga 하이재킹을 시연합니다.
Long-Running-Action 헤더를 통한 saga 하이재킹camel-core의 SagaProcessor가 모든 exchange에서 Long-Running-Action 메시지 헤더를 기반으로 saga 코디네이터를 선택했던 Apache Camel 취약점에 대한 실행 가능한 개념 증명(PoC) 재현기입니다. 해당 헤더 이름에는 Camel 접두사가 없어서, 컨슈머 헤더 필터가 제거하는 네임스페이스 밖에 위치합니다. 따라서 외부 발신자가 인바운드 메시지에 이 헤더를 제공하여 자신의 exchange가 참여할 saga를 지정할 수 있고, 이를 통해 자신의 요청을 다른 누군가가 시작한 장기 실행 액션에 연결하거나(또는 자신이 시작하지 않은 액션에 보상을 연관시킬 수 있습니다). 노출 범위는 saga를 실행하는 배포로 제한되지만, 해당되는 경우 발신자가 exchange가 어느 saga에 속하는지를 제어하게 됩니다(CWE-20).
| 런타임 | 디렉터리 | 스택 |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-spring-boot 4.22.0 (영향받음; 4.22.1에서 수정) |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.39.0 + camel-quarkus-saga (Camel 4.22.0, 영향받음; 수정된 대조군 CQ 3.40.0 / Camel 4.22.1) |
두 모듈 모두 실제 camel-core SagaProcessor를 대상으로 영향받는 동작 및 수정된 동작을 시연합니다.
드라이버는 수정 사항 자체의 회귀 테스트(SagaHeaderCannotSelectCoordinatorTest)를 그대로 반영합니다. 이 드라이버는 인메모리 saga 서비스로 뒷받침되는 saga 라우트 from("direct:…").saga().propagation(MANDATORY)를 구성합니다. 이 서비스는 해석 요청을 받은 모든 id를 기록한 다음, 인바운드 헤더 Long-Running-Action = a-saga-id-from-the-wire를 담은 exchange 하나를 전송합니다. 이 id는 외부 발신자가 전송 경로에 실을 id입니다. 판별 기준은 단순히 어떤 saga id가 서비스에 도달하는가입니다:
a-saga-id-from-the-wire가 조회됩니다 — 즉 메시지가 코디네이터를 선택한 것입니다.두 빌드 모두에서 MANDATORY exchange는 결국 실패합니다(참여할 실제 saga가 없기 때문). 취약점은 이 실패가 아니라 공격자가 선택한 id가 코디네이터를 선택하는 데 사용되었다는 사실 자체이며, 이것이 판별 기준이 결과가 아닌 조회를 관찰하는 이유입니다.
# Camel Spring Boot
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected: wire id looked up = true; >>> PROVEN
docker compose down
# Patched control
mvn clean package -Dcamel.version=4.22.1
java -jar target/cve-2026-85312-saga-header-hijack-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack # fixed: wire id looked up = false; >>> Not exploited
# Camel Quarkus
cd camel-quarkus
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected (Camel 4.22.0): wire id looked up = true
docker compose down
# Patched control: CQ 3.40.0 ships Camel 4.22.1
mvn clean package -Dcamel-quarkus.version=3.40.0 -Dquarkus.platform.version=3.40.0
java -jar target/quarkus-app/quarkus-run.jar &
curl -s http://localhost:8080/exploit/attack # fixed: wire id looked up = false
| 속성 | 값 |
|---|---|
| 구성 요소 | camel-core (SagaProcessor.getCurrentSagaCoordinator) |
| CWE | CWE-20 (부적절한 입력 검증) |
| 심각도 | MEDIUM |
| 공격 벡터 | 외부 발신자가 saga EIP를 실행하는 라우트로 향하는 인바운드 메시지에 접두사 없는 Long-Running-Action 헤더를 제공함 |
| 영향 | 발신자가 교환이 참여할 saga를 지정함 — 다른 당사자의 장기 실행 작업에 연결되거나 보상이 잘못 연관됨 |
| 영향받는 버전 | 4.0.0부터 4.18.5 이전, 4.19.0부터 4.22.1 이전 |
| 수정된 버전 | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24449 |
| 크레딧 | Claude Security Scan Tool |
권고문: https://camel.apache.org/security/CVE-2026-85312.html
Quarkus의 영향받는 모듈은 CQ 3.39.0 (Camel 4.22.0)을 기반으로 빌드됩니다. 패치된 컨트롤은 CQ 3.40.0 (Camel 4.22.1)입니다.
SagaProcessor는 이제 saga 서비스가 그러한 프로토콜에 참여한다고 알릴 때에만
Long-Running-Action 헤더를 참조하며, 이는 새로운
CamelSagaService.isLongRunningActionHeaderSupported()를 통해 이루어집니다 (기본값 false; LRA 서비스는 이를 true로 재정의함).
removeHeaders("*") 후에도 유지되는 내부 교환 상태가 saga id의 정상적인 전달자로 남으므로, 메시지는 더 이상
외부 코디네이터를 실행하지 않는 서비스의 코디네이터를 선택할 수 없습니다.
신뢰할 수 없는 발신자로부터 메시지를 수락하는 모든 컨슈머에서 신뢰 경계 지점에
removeHeaders("Long-Running-Action")를 사용하여 헤더를 제거하십시오.
이 저장소는 교육 및 방어 목적으로 게시됩니다: Apache Camel 사용자가 취약점을 이해하고, 영향을 받는지 확인하며, 업그레이드가 문제를 해결하는지 검증할 수 있도록 돕기 위함입니다. 데모는 인메모리 saga 서비스와 함께 프로세스 내에서 saga 라우트를 실행하며, "공격자" saga id는 무해한 자리 표시자 문자열입니다. 소유하거나 운영하지 않는 시스템에 이 자료를 사용하지 마십시오.