This post is also available in: English (英語)
概要
Cobalt Strikeは商用の脅威エミュレーションソフトウェアで、ネットワークに長期的にひそむアクターをエミュレートします。Beaconと呼ばれるこのアクターは外部TeamServerと通信してコマンド&コントロール(C2)トラフィックを模倣します。汎用性が高く、レッドチームの正規ツールとしてよく利用されますが、脅威アクターの実際の攻撃でも広く使用されています。この汎用性の高さはCobalt Strike にそなわる多くの機能に起因しています。たとえばC2サーバーへ送信するメタデータを暗号化・復号するプロセスなどがその例です。
以前のブログ「Cobalt Strike解析&チュートリアル: Cobalt Strikeによるメタデータのエンコードとデコード」では、暗号化されたメタデータがHTTPトランザクション用にエンコードされることを学びました。
Cobalt Strike Beaconは、Phone Home通信 (C2サーバーへの連絡通信)時に、RSAアルゴリズムの公開鍵でメタデータ(侵害システムに関する情報)を暗号化し、Cobalt Strike TeamServerに送信します。TeamServerは秘密鍵を使ってBeaconの平文メタデータを復元し、Beaconクライアントを識別します。また復号されたメタデータからはAESの共通鍵を抽出可能です。クライアントとサーバーはこのAES鍵を使ってその後のリクエストデータやレスポンスデータの暗号化と復号を行い、C2トラフィック通信を終了します。
本稿では、データの暗号化・復号アルゴリズム、鍵の生成・抽出、メタデータの暗号化・復号、メタデータのスキーマ定義の詳細説明とデモを行います。また、C2トラフィック通信で暗号化・復号アルゴリズムがどのように機能するかを示し、なぜ汎用性が高いとCobalt Strikeがエミュレータとして有効で、防御が難しくなってしまうのかについても示します。ここが本稿でもとりわけ興味深い部分のひとつでしょう。
関連する Unit 42 のトピック | Cobalt Strike, C2, Tutorials |
目次
データ暗号化・復号アルゴリズム
メタデータのスキーマ定義
公開鍵/秘密鍵の生成・抽出
RSAとAESによるC2メタデータの暗号化/復号の一例
結論
IoC
追加リソース
データ暗号化・復号アルゴリズム
Cobalt Strike Beaconは、TeamServerと通信するさい、共通鍵暗号(AES)と公開鍵暗号(RSA)の暗号アルゴリズムを組み合わせて使用します。その後、TeamServerが新たな公開鍵と秘密鍵のペアを生成し、この鍵ペアを.cobaltstrike.beacon_keysファイルに格納します。このファイルはCobalt Strikeのsetupの解凍先ディレクトリと同じディレクトリに格納されます。ファイルがすでに存在する場合は同じキーペアが使われます。
公開鍵暗号アルゴリズムはRSA/ECB/PKCS1Padding方式、共通鍵アルゴリズムはAES/CBC/NoPadding方式でデータの暗号化/復号を行います。AESアルゴリズムは、ハードコードされた初期化ベクトル(IV)で初期化されます。この静的IVはabcdefghijklmnopです。
図1はCobalt Strike BeaconとTeamServerとの間のC2トラフィックを示しています。
メタデータのスキーマ定義
メタデータはその名が示す通り標的に関する情報を含んでいます。メタデータは先頭に4バイトのマジックナンバー(0xBEEF)をもつ構造化されたフォーマットになっています。図2にメタデータの構造を示します。
復号されたデータはさまざまな情報のかたまり(Blob)になっています。復号されたBlobの構造はCobalt Strikeのバージョン4.0で更新されており、Beaconはメタデータにさらに多くの情報を追加しています。データフィールドのサイズは4バイトで、これは作者が将来的にメタデータの構造を更新する可能性を示唆しています。図3は、メタデータに詰め込まれているさまざまな情報の種類を示したものです。この構成は現在の実装に準じています。
以下、復号されたデータの各データフィールドの内訳を順に説明します。
- 最初の16バイトはBeaconが生成するランダムバイトで、各実行プロセスに固有です。BeaconとTeamServerはこの16バイトからAES鍵とHMAC鍵を生成します。プロセスはこれら16バイトのSHA256ハッシュを計算します。SHA256ハッシュの最初の16バイトが共通暗号のAES鍵として割り当てられ、残りの16バイトがメッセージ認証コード用のHMAC鍵になります。
- 次のリトルエンディアンの2バイトはANSI文字セットとしてデコードされます。文字セットの全リストについてはコードページ識別子に関するドキュメントを参照してください。
- その次のリトルエンディアン2バイトはOEM文字セットに割り当てられています。
- 4バイトのビッグエンディアンはBeacon IDで、各Beaconには一意なIDが与えられます。
- 4バイトのビッグエンディアンは被害マシン上で稼働するBeaconのプロセスIDです。
- 2バイトはポートとしてデコードされます。
- 1バイトはフラグとしてデコードされます。現在のCobalt Strikeの実装では、このフラグの値でBeaconのアーキテクチャ(32ビット/64ビット)を設定しています。
- 2バイトがBeaconのバージョン番号です。これらのバイトは間に「.」を挿入した文字列に変換されます。例: A.B
- 2バイトはBeaconのビルドバージョンとしてデコードされます。
- 次の4バイトのビッグエンディアンの値は関数へのポインタをプレフィクスするのに使用されます(Beaconのアーキテクチャが64ビットの場合)。これら4バイトは32ビットアーキテクチャの場合は破棄されます。
- 続く2つの4バイト値はGetModuleHandleAとGetProcAddressへのポインタです。これらの値を使うことでシェルコードは明示的にインポートされていない関数を解決できるようになります。Beaconが64ビットの場合は先の値にプレフィクスを付けた結果の値全体が変数に格納されます。
- 次の4バイトは標的のIPアドレスです。これらのバイトは後でIPv4として読み取り可能なアドレスに変換されます。
- 最後のバイト列はUTF-8で、この値は「\t」で区切られます。現バージョンではこのデータは「ComputerName\tUserName\tBeaconProcessName」という構造になっています。
公開鍵/秘密鍵の生成・抽出
Beaconはチェックインするさい、RSA公開鍵で暗号化したメタデータのBlobをTeamServerに送信します。TeamServerはこれを秘密鍵で復号して平文のメタデータを復元し、この後の通信で使うほかのメタデータとAES鍵とを抽出します。AES鍵は解読が極めて困難な公開鍵暗号で暗号化されているので、これでMitM攻撃(中間者攻撃)や検出を回避できます。さらに、C2通信は共通鍵で暗号化されるのでマーカーに使えるフィンガープリントを見つけるのが難しくなります。
プロファイルをロードして起動したTeamServerは、公開鍵と秘密鍵の鍵ペアを生成し、それらをTeamServerのルートディレクトリの.cobaltstrike.beacon_keysファイルに格納します(ファイルが存在しない場合)。
この公開鍵/秘密鍵は、GitHubで共有されている鍵をダンプするJavaプログラムを使うと抽出できます。その方法を以下に示します。
1. 公開鍵/秘密鍵ペアは.cobaltstrike.beacon_keysにjava.security.KeyPairオブジェクトとして格納されています(図4参照)。
2. TeamServerのルートディレクトリで図5のJavaプログラムをコンパイルして実行すると、公開鍵/秘密鍵のペアがbase64でエンコードされます。
RSAとAESによるC2メタデータの暗号化/復号の一例
以下に例をあげ、Cobalt Strike BeaconのメタデータやC2のHTTPトラフィック通信のコンテキストでの暗号化・復号がどのように機能するかを説明します。
この分析ではVirusTotalから直接ダウンロード可能な実サンプル(SHA256:50ea11254f184450a7351d407fbb53c54686ce1e62e99c0a41e7e3e505d60c)を使います。
このサンプルのC2トラフィック分析は次の3つのセクションに分かれます。
これら3つのセクションでは暗号化/復号の分析により次のプロセスを説明しています。
- RSA公開鍵と漏えいした秘密鍵を使ってメタデータを復号し、AES鍵とHMAC鍵を取得する
- AES鍵を使ってHTTP GETレスポンス内の暗号化されたタスクデータを復号する
- AES鍵を使ってHTTP POSTリクエストボディ内のタスク実行結果を復号する
Cobalt Strike Beaconのダウンロード
1768.pyというスクリプトで設定をパースすると、このBeaconはRSA秘密鍵が漏えいしたバージョンのCobalt Strikeソフトウェアで生成されていることがわかります。
C2 Beaconハートビート
Beaconのダウンロードと実行後はTeamServerへのC2チェックインが行われ、HTTPリクエストのCookieに感染マシンに関する暗号化されたメタデータ情報が漏出されます。
cs-crypto-parser.pyスクリプト(cs-mitm.pyスクリプトを若干修正したバージョン)を実行してメタデータ情報を復号します。このさいCookieからの値(XjaoBxbLchqKBL/s/m8Pgz/wHRbx660/2Aa8Toa9T/AJ0Ns8mgjPBWdYIL9mEFM1DE/5GXGCSURf6RP+wxo5Zx0G/yENlMTuzPaCO11/XPNxRj69Nf6++05qe7iMKfg8D4ZFGiEQAVo6UXqUteZlAqubJ+uNZBglsyioa+aSQw=)を第一引数として渡す必要があります。
RSAの復号
このスクリプトが実行する最初のタスクはパラメータを2つ受け取るRSADecrypt()関数の呼び出しです。1つめのパラメータは秘密鍵、2つめのパラメータは暗号化されたCookieの値です。このタスクが完了するとRSA秘密鍵をデコードしてインポートし、新たなPKCS1オブジェクトをインスタンス化します。最後にこのスクリプトはdecrypt関数を呼び出し、暗号化されたデータ変数を引数としてこの関数に渡し、暗号文の復号を実行します。
出力結果としてメタデータの詳細な内訳が16進数値とともに表示されます。
復号されたメタデータの構造については本稿の「メタデータのスキーマ定義」セクションを参考にしてください。
C2のタスクリクエストとレスポンス(コールバック)
AES鍵とHMAC鍵
ペイロードはCBCモードのAES-256暗号にHMAC-SHA-256鍵付きハッシュアルゴリズムを指定して暗号化されます。RSA秘密鍵や復号されたデータへのアクセスがあるのでこれには生の鍵も含まれます。この鍵は16バイトで、復号されたペイロードの8バイト目に位置しています。このマルウェアサンプルの場合、鍵は1a 13 7e 76 f9 15 6a 67 f9 99 af d6 57 64 75 bdです(16進数表記)。AES鍵とHMAC鍵を生成するため生の鍵からSHA256ハッシュが計算されますが、計算された結果は、前半(16バイト)が実際のAES鍵で後半(16バイト)がHMAC鍵になります。下の図11はcrypto-parserスクリプトを実行したさいの計算の様子を示したものです。
C2タスクリクエスト
C2チャンネルが確立されてチェックインが行われると、Beaconはチェックや新しいタスクの実行を行います。図12は、タスクリクエストがTeamServerからのレスポンスペイロードを受信した様子を示しています。
ここで48バイトのペイロードデータをスクリプトに渡して復号します。暗号化されたBlobの最後の16バイトはHMAC Signatureで、これがリクエストの完全性の基準として用いられます。図13は、タスクペイロードのデータをパースして復号したものです。
復号処理を担っているのがDecrypt()関数で、この関数が以下の処理を行います。
- 暗号化されたデータをパラメータとして受け取る
- 暗号化されたペイロードからHMAC Signatureを抽出する
- 暗号化されたペイロードのHMAC鍵を使ってHMAC Signatureを計算・検証する
- AES鍵をロードしてモード(CBC)と初期化ベクトル(IV)を設定する
- 暗号化されたペイロードを復号する
C2タスクレスポンス
BeaconがC2サーバーからのタスクを受けとって実行すると、その結果が収集されてTeamServerに返されます。
上記と同じDecrypt()関数を使って暗号化されたペイロードが提供されます。ただし、Cobalt Strikeのタスクレスポンスでは最初の4バイトが復号対象にならず、関数に渡されるデータからはこれら4バイトが除外されます。
このリクエストに含まれるタスクデータのレスポンスは、ASCII文字列BOBSPC\\Administratorで、感染したコンピュータのマシン名とユーザー名を表しています。
結論
Cobalt Strikeは侵害後のアクターをエミュレートする強力なツールです。先に説明したメタデータの暗号化・復号は巧妙で、セキュリティ検出回避をねらって設計されています。セキュリティアプライアンス単体ではCobalt Strikeの攻撃を防げないので、ファイアウォール、サンドボックス、エンドポイント、さらにこれらすべての要素を統合してくれるソフトウェアのセキュリティソリューションを組み合わせて使うことが必要になります。
パロアルトネットワークスのお客様は、本稿で説明したCobalt Strikeの攻撃同様の攻撃から次の方法で保護されています。
- 脅威防御シグネチャ86445と86446を含む次世代ファイアウォール(NGFW)は、デフォルトプロファイルのBase64メタデータエンコードを行うHTTP C2リクエストを識別します。Advanced Threat Preventionには、シグネチャに頼らずにこれらの攻撃を検知する新機能があります。
- NGFW用のセキュリティサブスクリプションWildFireとCortex XDRはCobalt Strike Beaconを識別・ブロックします。
- AutoFocusをお使いのお客様は次のタグを使用してこれらのアクティビティを追跡できます: CobaltStrike
IoC (侵害指標)
Cobalt Strike サンプル
- 50ea11254f184450a7351d407fbb53c54686ce1e62e99c0a41ee7ee3e505d60c
Cobalt Strike Beacon サンプル
- /lNj8
- SHA256ハッシュ:
- e712d670382ad6f837feeb5a66adb2d0f133481b5db854de0dd4636d7e906a8e
- SHA256ハッシュ:
Cobalt Strike TeamServerのIPアドレス
- 92.255.85[.]93
追加リソース
- Cobalt Strike Training (Cobalt Strikeトレーニング)
- Cobalt Strike Malleable C2 Profile (Cobalt Strike Malleable C2プロファイル)
- Cobalt Strike Decryption with Known Private Key (Cobalt Strikeを既知の秘密鍵で復号する)
- Cobalt Strike解析・チュートリアル: Malleable C2プロファイルでCobalt Strike検出が難しくなる理由
- Cobalt Strike解析&チュートリアル: Cobalt Strikeによるメタデータのエンコードとデコード