
Reprodutor de prova de conceito executável para CVE-2026-78162, demonstrando desserialização Java não autenticada no Apache Camel camel-hazelcast em Spring Boot e Quarkus.
Reprodutor de prova de conceito executável para a vulnerabilidade do Apache Camel em que o camel-hazelcast criava instâncias Hazelcast sem um JavaSerializationFilterConfig em dois caminhos de configuração que o endurecimento do CVE-2026-43865 nunca alcançou. Nesses caminhos, um membro/cliente Hazelcast construído pelo Camel desserializa valores lidos do cluster sem qualquer restrição de classe, de modo que um atacante capaz de publicar no cluster pode fazer com que um objeto Java serializado de sua escolha seja desserializado dentro da camada de serialização do Hazelcast — execução remota de código (CWE-502). Clusters Hazelcast não têm autenticação nem TLS habilitados por padrão.
Este reprodutor aciona o mais claro dos dois caminhos: ReplicatedHazelcastAggregationRepository, que sobrescreve doStart() sem chamar super.doStart() e, em uma build afetada, inicia seu próprio membro local sem aplicar o filtro padrão. (O caminho irmão, HazelcastDefaultComponent#getOrCreateHzClientInstance() para hazelcastMode=client, é coberto pela mesma correção.)
| Runtime | Diretório | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-hazelcast 4.22.0 (afetado; corrigido em 4.22.1) |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.29.0 + camel-quarkus-hazelcast 3.29.0 (Camel 4.15.0, afetado) |
Controle corrigido-vs-afetado: a correção é distribuída no Camel 4.18.5 / 4.22.1 / 4.23.0. O módulo Spring Boot pode executar tanto a build afetada (4.22.0) quanto a build corrigida (4.22.1), de modo que também demonstra o comportamento corrigido. Nenhum Camel Quarkus lançado ainda inclui um Camel corrigido (o mais recente, 3.29.0, está no Camel 4.15.0), portanto o módulo Quarkus demonstra apenas o caso afetado.
A aplicação executa uma rota Camel apoiada por um ReplicatedHazelcastAggregationRepository sem nenhuma HazelcastInstance fornecida externamente, de modo que o repositório inicia seu próprio membro Hazelcast local (cluster padrão dev, porta 5701). Na build afetada, esse membro não possui JavaSerializationFilterConfig.
Um cliente atacante então entra no cluster e publica um objeto serializado no ReplicatedMap de suporte. Um cliente Hazelcast apenas envia bytes — ele não armazena nem desserializa valores de mapa —, portanto qualquer desserialização que ocorra é atribuível ao membro vítima. O objeto publicado é um marcador deliberadamente benigno, com.example.PwnMarker: ele não carrega cadeia de gadgets e não executa comando algum, apenas registra (via uma flag global da JVM) que seu readObject foi executado. Um atacante real publicaria aqui uma classe de gadget conhecida, para RCE — provar que a classe foi desserializada já é suficiente.
Como o filtro padrão da correção é uma lista de permissões de prefixos de nome de classe java., javax. e org.apache.camel., o com.example.PwnMarker é o oráculo perfeito:
PwnMarker é desserializado, readObject é executado no membro vítima → PROVADO.com.example.PwnMarker antes do readObject → java.lang.SecurityException: Resolving class com.example.PwnMarker is not allowed → não explorado.cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
Saída esperada numa build afetada:
=== CVE-2026-78162 — camel-hazelcast ReplicatedHazelcastAggregationRepository ===
=== missing JavaSerializationFilterConfig on the Camel-built member ===
Attacker client joined the victim cluster 'dev' at 127.0.0.1:5701.
Attacker published a com.example.PwnMarker into ReplicatedMap 'aggregation'.
Result:
>>> PROVEN: the Camel-built Hazelcast member deserialized an attacker-supplied, non-whitelisted
>>> class (com.example.PwnMarker) with no JavaSerializationFilterConfig in effect — its readObject
>>> executed inside the victim. A real attacker would publish a gadget class here instead, for RCE.
>>> PwnMarker.readObject executed inside the victim member; tag=attacker-rce-marker; thread=hz.*.partition-operation.thread-1
| Propriedade | Valor |
|---|---|
| Componente | camel-hazelcast (camel-hazelcast-starter / camel-quarkus-hazelcast) |
| CWE | CWE-502 (Desserialização de Dados Não Confiáveis) |
| Severidade | MÉDIA |
| Vetor de ataque | Um atacante que consiga publicar no cluster Hazelcast ao qual uma instância afetada está conectada; o membro/cliente construído pelo Camel desserializa o objeto publicado sem qualquer restrição de classe |
| Impacto | Execução remota de código dentro do processo Camel (por meio de uma classe gadget), antes de o Camel processar o exchange |
| Versões Afetadas | A partir de 4.0.0 antes de 4.18.5, a partir de 4.19.0 antes de 4.22.1 |
| Versões Corrigidas | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24413, CAMEL-24420 |
| Crédito | cattier da TCBS; Leon Zlobecki |
Aviso: https://camel.apache.org/security/CVE-2026-78162.html
HazelcastSerializationFilterHelper.applyDefault(...) ganhou uma sobrecarga ClientConfig e agora é chamado em ambos
os caminhos anteriormente descobertos — ReplicatedHazelcastAggregationRepository#doStart() e
HazelcastDefaultComponent#getOrCreateHzClientInstance() — de modo que toda configuração Hazelcast que o próprio Camel
constrói carrega o JavaSerializationFilterConfig padrão (lista de permissões java. / javax. / org.apache.camel., lista de bloqueio
java.net.). Um Config, ClientConfig ou HazelcastInstance fornecido pelo usuário permanece intocado. Este aviso
é um desdobramento de correção incompleta do CVE-2026-43865.
Forneça uma configuração Hazelcast explícita que carregue um JavaSerializationFilterConfig, ou injete um
HazelcastInstance pré-construído (uma configuração fornecida pelo usuário nunca é sobrescrita pelo Camel); defina o
-Djdk.serialFilter=... em toda a JVM; e habilite a autenticação e o TLS do cluster Hazelcast.
Este repositório é publicado para fins educacionais e defensivos: para ajudar os usuários do Apache Camel a entender a vulnerabilidade, verificar se estão afetados e confirmar que a atualização a resolve. O payload é um marcador benigno que não executa nenhum código. Não use este material contra sistemas que você não possui ou opera.