ActiveMQの脆弱性（CVE-2023-46604）を検証したった

:::note info
これは [ZOZO Advent Calendar 2023](https://qiita.com/advent-calendar/2023/zozo) カレンダーVol.4の3日目の記事です。昨日の投稿は@ymd_aaaさんの「[AndroidStudioからのGit操作でJava to Kotlinの差分を見やすくする](https://qiita.com/ymd_aaa/items/778d57dc55ac5c6f3408)」でした。
:::

# はじめに
この記事はApache ActiveMQの脆弱性（CVE-2023-46604）を[HacktheBox](https://www.hackthebox.com/)の「Broker」（以下リンク参照）で検証した際のメモになります。

https://app.hackthebox.com/machines/Broker

# CVE-2023-46604
Apache ActiveMQにRCEの脆弱性[CVE-2023-46604](https://activemq.apache.org/news/cve-2023-46604)が10月末に公開されていました。
## 影響を受けるバージョン
+ 5.18.3 以前の Apache ActiveMQ 5.18.0
+ 5.17.6 以前の Apache ActiveMQ 5.17.0
+ 5.16.7 以前の Apache ActiveMQ 5.16.0
+ 5.15.16 以前の Apache ActiveMQ
+ Apache ActiveMQ レガシー OpenWire モジュール 5.18.0 5.18.3 以前
+ Apache ActiveMQ レガシー OpenWire モジュール 5.17.0 5.17.6 以前
+ Apache ActiveMQ レガシー OpenWire モジュール 5.16.0 5.16.7 以前
+ Apache ActiveMQ レガシー OpenWire モジュール 5.8.0 5.15.16 以前
### 実際の被害
以下のようにHelloKittyランサムウェアファミリーから悪用された疑いがあります。

https://www.rapid7.com/ja/about/japan-blog-and-news/etr-suspected-exploitation-of-apache-activemq-cve-2023-46604/


## 修正バージョン
+ Apache ActiveMQ　5.18.3
+ Apache ActiveMQ　5.17.6
+ Apache ActiveMQ　5.16.7
+ Apache ActiveMQ　5.15.16

## POC
POCについても同時期に[Github](https://github.com/X1r0z/ActiveMQ-RCE)にてCommitされていることがわかります。
このPOCを皮切りに色々とPOCが出ています。今回は以下の2つのPOCを利用します。

### POC by evkl1d

https://github.com/evkl1d/CVE-2023-46604

### POC by VulnCheck

https://thehackernews.com/2023/11/new-poc-exploit-for-apache-activemq.html

# HacktheBox - Broker
このBOXは上記のCVE-2023-46604を内包したものになります。
EasyのBoxであり、初心者の方でも取り組みやすい内容になっています。是非ともRootフラグまでゲットしてもらえればと思います。
※今回はCVE-2023-46604の検証のために使うので、Rootフラグまでの攻略は割愛します。

### ポートスキャン
`rustscan`を用います。
```bash
┌──(root㉿kali-linux-2022-2)-[~]
└─# rustscan -a 10.10.11.243 --top --ulimit 5000
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
Please contribute more quotes to our GitHub https://github.com/rustscan/rustscan

[~] The config file is expected to be at "/root/.rustscan.toml"
[~] Automatically increasing ulimit value to 5000.
Open 10.10.11.243:22
Open 10.10.11.243:80
Open 10.10.11.243:1337
Open 10.10.11.243:8161
Open 10.10.11.243:1883
Open 10.10.11.243:5672
Open 10.10.11.243:45043
Open 10.10.11.243:61613
Open 10.10.11.243:61614
Open 10.10.11.243:61616
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")

[~] Starting Nmap 7.94 ( https://nmap.org ) at 2023-11-13 02:01 EST
Initiating Ping Scan at 02:01
Scanning 10.10.11.243 [4 ports]
Completed Ping Scan at 02:01, 0.23s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 02:01
Completed Parallel DNS resolution of 1 host. at 02:01, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 02:01
Scanning 10.10.11.243 [10 ports]
Discovered open port 1337/tcp on 10.10.11.243
Discovered open port 80/tcp on 10.10.11.243
Discovered open port 22/tcp on 10.10.11.243
Discovered open port 1883/tcp on 10.10.11.243
Discovered open port 5672/tcp on 10.10.11.243
Discovered open port 61616/tcp on 10.10.11.243
Discovered open port 61614/tcp on 10.10.11.243
Discovered open port 61613/tcp on 10.10.11.243
Discovered open port 45043/tcp on 10.10.11.243
Discovered open port 8161/tcp on 10.10.11.243
Completed SYN Stealth Scan at 02:01, 0.23s elapsed (10 total ports)
Nmap scan report for 10.10.11.243
Host is up, received echo-reply ttl 63 (0.21s latency).
Scanned at 2023-11-13 02:01:16 EST for 0s

PORT      STATE SERVICE     REASON
22/tcp    open  ssh         syn-ack ttl 63
80/tcp    open  http        syn-ack ttl 63
1337/tcp  open  waste       syn-ack ttl 63
1883/tcp  open  mqtt        syn-ack ttl 63
5672/tcp  open  amqp        syn-ack ttl 63
8161/tcp  open  patrol-snmp syn-ack ttl 63
45043/tcp open  unknown     syn-ack ttl 63
61613/tcp open  unknown     syn-ack ttl 63
61614/tcp open  unknown     syn-ack ttl 63
61616/tcp open  unknown     syn-ack ttl 63

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.60 seconds
           Raw packets sent: 14 (592B) | Rcvd: 11 (468B)
```
色々とPortが空いてますが、大体こういうのはhttpから探っていくことが多いです。

### Webの確認
80番Portを確認していきます。`nikto`コマンドでスキャンしてみます。
```bash
┌──(root㉿kali-linux-2022-2)-[~]
└─# nikto -h 10.10.11.243 -p 80                
- Nikto v2.5.0
---------------------------------------------------------------------------
+ Target IP:          10.10.11.243
+ Target Hostname:    10.10.11.243
+ Target Port:        80
+ Start Time:         2023-11-16 13:26:49 (GMT9)
---------------------------------------------------------------------------
+ Server: nginx/1.18.0 (Ubuntu)
+ /: The anti-clickjacking X-Frame-Options header is not present. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+ /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/
+ / - Requires Authentication for realm 'ActiveMQRealm'
+ /: Default account found for 'ActiveMQRealm' at (ID 'admin', PW 'admin'). Generic account discovered.. See: CWE-16
+ Root page / redirects to: http://10.10.11.243/index.html
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ nginx/1.18.0 appears to be outdated (current is at least 1.20.1).
```
何があるかもうある程度見えてますが、実際に80番ポートへアクセスしてみます。
![スクリーンショット 2023-11-16 13.25.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/700a439b-df14-b061-be8d-0e79f68c31be.png)
Basic認証を要求されますが、`nikto`にて見つけた`admin:admin`でログインできました。
![スクリーンショット 2023-11-16 13.26.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/b106cb91-2339-4b7b-376c-6166bb6d633a.png)
![スクリーンショット 2023-11-16 13.27.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/423ae5b7-782d-d99c-6bd1-186b01ffb3e1.png)
バージョンを探ると、`5.15.15`であることがわかります。脆弱ですね。

# POC検証
上記で紹介した2つのPOCを試してみます。
## その1
[evkl1dさんのPOC](https://github.com/evkl1d/CVE-2023-46604)を試します。
以下のようにGithubからクローンしてきます。
```bash
┌──(root㉿kali-linux-2022-2)-[~]
└─# git clone https://github.com/evkl1d/CVE-2023-46604     
Cloning into 'CVE-2023-46604'...
remote: Enumerating objects: 22, done.
remote: Counting objects: 100% (22/22), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 22 (delta 5), reused 13 (delta 3), pack-reused 0
Receiving objects: 100% (22/22), 5.10 KiB | 5.10 MiB/s, done.
Resolving deltas: 100% (5/5), done.
```
このPOCをよく読むと、Pythonを実行してExploitするのですが、その際に`ClassPathXmlApplicationContext`のクラスを利用しています。
このインスタンスの生成時、リモートにあるXMLファイルの設定ファイルを参照してOSのコマンドを実行するといったものです。
[CVE-2020-14882](https://nvd.nist.gov/vuln/detail/CVE-2020-14882)のPOCでもあったJavaでよく見るやつですね。

このクラス名とメッセージ（XMLのURL）をActiveMQで使われているOpenWireのプロトコル（今回はPort 61616）に送信し、`BaseDataStreamMarshaller`クラス周りに叩き込めばRCEができるはずです。
詳細は以下の記事を参照してください。

https://paper.seebug.org/3058/

### 実行
XMLを外部から参照できるようにhttpサーバを以下のように建てます。
```bash
┌──(root㉿kali-linux-2022-2)-[~]
└─# python3 -m http.server 80
```
次にXMLファイルを編集して以下のようにリバースシェルコマンドを叩き込むように変更します。
![スクリーンショット 2023-11-16 13.51.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/82eb6c0c-d593-9a74-2fbe-3774db617422.png)
そして、PythonのPOCを実行します。
![スクリーンショット 2023-11-16 13.47.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/6e327ca9-9a98-b876-9853-30054fb5d60b.png)
簡単ですね。3つ目の`<value>`を編集すればどんなコマンドでも叩き込めます。

## その2
[VulnCheckさんのPOC](https://vulncheck.com/blog/cve-2023-44604-activemq-in-memory)を利用します。
と言ってもXMLとPOCコードを変更するだけで済みます。
XML以下のように編集します（一部マスクしてます）。
![スクリーンショット 2023-11-16 16.20.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/51a4ec9f-6b58-8f88-320c-fd49cb9556ba.png)
記載しているBase64コードの内容ですが、基本的にJavaのコードとなります。エンコード前は以下のようになります。
![スクリーンショット 2023-11-16 16.19.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/c5798b44-671a-a434-d544-ed4ee48199ac.png)
次にPythonのExploitコードを以下のように編集します。
```python
 class_name = "org.springframework.context.support.FileSystemXmlApplicationContext"
```
### 実行
変更したExploitコードを実行します。
![スクリーンショット 2023-11-16 16.21.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/601d984e-ed0c-9fcf-25f4-dcf263f71664.png)
プロンプトは帰ってきていませんが、コマンドは実行できているのがわかります。

## 2つのPOCの違い
2つのPOCの違いは、XMLファイルの内容と使うクラスです。
`ClassPathXmlApplicationContext`ではなく`FileSystemXmlApplicationContext`,`SpEL`を利用します。

この違いは何かをpspyのToolを使って確認します。
その1のPOCでは以下のようにシェルジャンプを行うことで任意のコードが実行されます。
![スクリーンショット 2023-11-16 16.52.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/2d0a3050-30b8-6a2c-7333-e68717b8bf2a.png)
その2のPOCではメモリ上にJavaのコードが展開されて実行されるので、シェルジャンプを行う必要がありません。
![スクリーンショット 2023-11-16 16.56.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2036848/8f5e0dd9-d788-c179-7689-7e002670f96a.png)
要するにメモリ上であれこれするようにJavaコードを構築してしまえば色々できるということです。
BlueTeamからの検知回避に利用できます。

# BlueTeamで確認すべき観点
+ ActiveMQのバージョンが脆弱なのか
+ OpenWireプロトコルを使用しており、外部からアクセス可能なのか
+ ActiveMQから外部のXMLファイルを参照可能なのか（ActiveMQ発の通信ができるか）

# まとめ
今回はCVE-2023-46604の検証をHacktheBoxの「Broker」で行いました。
脆弱性を検証できる環境は少ないのでこういうBOXはありがたいですね。

明日は@tippyさんです。