サイバーセキュリティ チュートリアル

Cobalt Strike解析&チュートリアル: Cobalt Strikeによるメタデータのエンコードとデコード

Clock Icon 4 min read

This post is also available in: English (英語)

概要

Cobalt Strikeは商用の脅威エミュレーションソフトウェアで、ネットワークに長期的にひそむアクターをエミュレートします。Beaconと呼ばれるこのアクターは外部チームサーバーと通信してコマンド&コントロール(C2)トラフィックを模倣します。汎用性が高く、レッドチームの正規ツールとしてよく利用されますが、脅威アクターの実際の攻撃でも広く使用されています。この汎用性の高さはCobalt Strike にそなわる多くの機能に起因しています。たとえばC2サーバーへ送信するメタデータを難読化するエンコード用のアルゴリズムなどがその例です。

前回のブログ「Cobalt Strike解析&チュートリアル: Malleable C2プロファイルでCobalt Strike検出が難しくなる理由」で、攻撃者またはレッド チームが HTTP トランザクションに対し、Malleable C2 プロファイル内でメタデータ エンコード インジケーターを定義できることを学びました。Cobalt Strike Beaconは、Phone Home通信 (C2サーバーへの連絡通信)時に、侵害システムに関する情報であるメタデータをCobalt Strike TeamServerに送信します。レッドチームや攻撃者は、このメタデータをどのようにエンコードし、HTTPリクエストで送信し、C2トラフィック通信を終了させるかを定義する必要があります。

本稿は、エンコードアルゴリズム、Cobalt Strikeフレームワークで使用されるエンコードタイプの定義と違い、実際に観測されている悪意のある攻撃について解説します。解説ではC2トラフィック通信中にエンコード用・デコード用のアルゴリズムがどのように機能するかを示すほか、なぜ汎用性が高いとCobalt Strikeがエミュレータとして有効で、従来型ファイアウォール対策の設計が難しくなってしまうのかについても示します。

関連する Unit 42 のトピック Cobalt Strike, C2, Tutorials

目次

メタデータのエンコード用アルゴリズム
Base64エンコードとデコード
Base64URLエンコードとデコード
NetBIOSエンコードとデコード
NetBIOSUエンコードとデコード
マスクエンコードとデコード
実際の攻撃事例
結論
IoC
追加リソース

メタデータのエンコード用アルゴリズム

Cobalt Strikeがサポートするエンコード方式は5つあります。RSAで暗号化したメタデータをエンコードすれば、ネットワークプロトコルでこの暗号化したバイナリデータを簡単に転送できるようになります。

Cobalt Strikeがサポートするメタデータのエンコード方式は、Base64、Base64URL、Mask、NetBIOS、NetBIOSUです。
図 1. Cobalt Strike プロファイルのエンコード方式

Base64エンコードとデコード

Base64エンコードとデコードは標準的なRFC用アルゴリズム実装です。作者はBase64の文字集合になんら変更をくわえていません。データのエンコードとデコードに使用される文字の一覧は次のとおりです。

[ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' ]

MalleableプロファイルでのBase64アルゴリズムの使用について、実際の例をとりあげて理解しましょう。

1. プロファイルのメタデータ

Havex.profileは侵害システムに関するメタデータ情報をBase64エンコードで変換してから送信します。図2は、メタデータがBase64エンコードアルゴリズムでエンコードされ、その結果がCookieヘッダに配置される様子を示しています。

Havexプロファイルのメタデータエンコードオプション。この図が示すようにメタデータはBase64エンコードアルゴリズムでエンコードされ、その結果がCookieヘッダに配置される。
図 2. Havexプロファイル内のメタデータエンコードオプション

2. HTTP C2トラフィック

図3はこのプロファイルが生成したHTTP C2トラフィックです。ハイライト表示した部分が侵害システムに関するメタデータをBase64エンコードしたものです。

Havexプロファイルが生成したHTTP C2トラフィック。ハイライト表示した部分が侵害システムに関するメタデータをBase64エンコードしたものです。
図 3. Havexプロファイルが生成したHTTP C2トラフィック

3. Base64デコード

  • エンコードされたメタデータは何を使ってデコードしてもかまいません。私たちはPythonのBase64 ライブラリでデコードしました。図4はこのデータをデコードして16進数で表示するスクリプトのサンプルです。
  • 以下はこのスクリプトでデコードしたデータで、侵害システムに関するRSA暗号化されたメタデータです。
    "751990bee317e74e4f2aa6f13078ef22dd884e065b738f8373f49dee401a069d5dfd1d3e39e94cc637e21364e1fd71ab3322fb9c7a987fc6aa27dfab981f077e7ddc2f20aba8e9d841250adc4edd4d15082445869278f2bbcf66e145aa74152a22b85c9b6c5f15d69f7d8b3708b33deea7198683d6468bd0424f537617f759b5"
サンプルのPythonスクリプト。これでデータをデコードして16進数で表示する
図 4. サンプルのPythonスクリプト。これでデータをデコードする

Base64URLエンコードとデコード

Base64URLはBase64エンコードアルゴリズムの変形版で、URLとファイル名を問題なく扱える文字集合をエンコードとデコードに使用します。以下がその文字集合です。

[ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' ]

標準Base64文字集合との違いは、変形版が「+」を「-」に、「/」を「_」に置き換えているところです。パディング文字の「=」はエンコードデータには含まれません。通常、URIではパーセントエンコードが行われるためです。

MalleableプロファイルでのBase64URLアルゴリズムの使用について、実際の例をとりあげて理解しましょう。

1. プロファイルのメタデータ

Cnnvideo_getonly.profileはメタデータ情報の変換にBase64URLエンコードを使います。なお、このプロファイルは正規のCNN HTTPトラフィックを模倣していることからその名がついていますが、当該組織とは無関係なので注意してください。さて、図5はBase64URLエンコードアルゴリズムでメタデータをエンコードし、パラメータgにデータをアペンドしたところを示しています。

このサンプルでは、メタデータをBase64エンコードアルゴリズムでエンコードし、そのデータをパラメータgにアペンドしている。
図 5. Cnnvideoプロファイルでのメタデータエンコード

2. HTTP C2トラフィック

図6はBeaconが生成するHTTP C2トラフィックを示したものです。パラメータの値は侵害システムに関するメタデータをBase64URLでエンコードしたものです。

Beaconが生成するHTTPトラフィック。パラメータの値は侵害システムに関するメタデータをBase64URLでエンコードしたものです。
図 6. Cnnvideoプロファイルが生成したHTTP C2トラフィック

3. Base64URLデコード

このデータのデコード方法はいくつかあります。

  • 「+」を「-」に、「_」を「/」に置き換えてパディング文字の「=」を追加する。置換した文字列は標準Base64エンコードデータになるので任意のBase64デコードツールを使って暗号化メタデータを得られる。
  • スクリプト言語に処理させる。図7にこのデータをデコードするPythonスクリプトのサンプルを示す。urlsafe_b64decode命令は文字を置き換えるだけでパディング文字は追加しないのでこのサンプルでは「=」を追加してBase64エンコードと互換の出力を得ている。パディング文字はもっと追加してもよい。Pythonはパディングが少なすぎる場合にのみエラーを返す。
  • このスクリプトで出力されるRSAで暗号化されたメタデータは次のとおり。"60495dff002eddaa0c409aaaae0fda592810993ae0ae319c87d62b65c54d92447daf2c1bc84930c5d90ed3a023227e254d3a2c28763be372bb7444ef5719d5948b99d33ede3775f51c216bba97bc5fd4777e819517e89a737284c784bdc30b1d6b3b7debe2448c1dc28b00e3ac611fd5a8fd070502f3f7f672786f6b5787af51"
サンプルのPythonスクリプト。これでデータをデコードする。urlsafe_b64decode命令は文字を置き換えるだけでパディング文字は追加しない。このサンプルでは '=' を追加してBase64エンコードと互換の出力を得ている。
図 7. Base64URLをデコードするPythonスクリプト

NetBIOSエンコードとデコード

NetBIOSエンコードはNetBIOSサービス名のエンコードに使用されます。Cobalt StrikeはC2通信で被害システムのメタデータを転送するさいこのアルゴリズムでエンコードしています。

NetBIOSのエンコードアルゴリズムは各バイトを2バイトのASCII文字で表現します。入力バイトの各4ビット(これを「ニブル」という)に2進数の右寄せ/ゼロ埋めを行い、それぞれを別のバイトとして扱います。その数値は次にASCII文字の「a」の値に加算され、結果として得られたバイトもそれぞれ別のバイトとして保存されます。エンコードに使用する文字集合は[a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']です。

図8はエンコード処理の様子を示したものです。

NetBIOSのエンコード処理を元のバイトからニブルを分割する手順、最後に'a' (16進数で0x61)を追加する手順まで実演。
図 8. NetBIOSのエンコード処理

MalleableプロファイルでのNetBIOSアルゴリズムの使用について、実際の例をとりあげて理解しましょう。

1. プロファイルのメタデータ

Ocsp.profileは被害システムのメタデータ変換にNetBIOSエンコードを使います。図9は、メタデータがNetBIOSエンコードアルゴリズムでエンコードされる様子を示しています。得られたデータはURIにアペンドされます。

メタデータがNetBIOSアルゴリズムでエンコードされています。得られたデータはURIにアペンドされます。
図 9. OCSPプロファイルでのメタデータエンコード

2. HTTP C2トラフィック

図10はBeaconがOCSPプロファイルで生成するHTTPトラフィックを示したものです。

図 10. OCSPプロファイルが生成したHTTP C2トラフィック
図 10. OCSPプロファイルが生成したHTTP C2トラフィック

3. NetBIOSデコード

図11は、NetBIOSでエンコードされたメタデータをデコードするPythonの実装です。

スクリプトの出力は侵害システムに関するメタデータをRSAで暗号化したものです。"5725245edcb589b305e33e02da1cda208ed083bed8a1ae0b3a87da0f9d6ebe31025ab67c58572acb9757288cc2e78bea414249fa8cb0783485a1b5a3c0863501fc1c89c6ac59b7129c51cacbfa197cc64eea31ec8ac204cbcdbefaecf19762f9efcc56280f3e9b183c37f98f371f5e1c08b645524646d7010af4408f4ebb8a2f"

NetBIOSでエンコードされたメタデータをデコードするPythonの実装。
図 11. NetBIOSエンコードをデコードするPythonスクリプト

NetBIOSUエンコードとデコード

NetBIOSUは先のNetBIOSエンコードアルゴリズムを若干変更したもので、エンコードに使用する文字集合が異なっています。NetBIOSUの文字集合は、通常のNetBIOSアルゴリズムで使用される文字集合を大文字にしたもので、その内容は['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P']です。

NetBIOSUのエンコード処理はNetBIOSのアルゴリズムと同じです。詳しくは、図8を参照してください。

MalleableプロファイルでのNetBIOSUアルゴリズムの使用について、実際の例をとりあげて理解しましょう。

1. プロファイルのメタデータ

Asprox.profileは被害システムのメタデータ変換にNetBIOSUエンコードを使います。図12は、メタデータがNetBIOSUエンコードアルゴリズムでエンコードされる様子を示しています。得られたデータはURIにアペンドされます。

メタデータがNetBIOSUエンコードアルゴリズムでエンコードされる様子。得られたデータはURIにアペンドされます。
図 12. asproxプロファイルでのメタデータエンコード

2. HTTP C2トラフィック

図13は、Beaconがasproxプロファイルで生成するHTTPトラフィックを示したもので、ハイライトした箇所が被害システムに関するメタデータです。

Beaconがasproxプロファイルで生成するHTTPトラフィック。ハイライトした箇所が被害システムに関するメタデータ。
図 13. Beaconがasproxプロファイルで生成するHTTPトラフィック

3. NetBIOSUデコード

図14は、NetBIOSUでエンコードされたメタデータをデコードするPythonの実装です。

スクリプトの出力は侵害システムに関するメタデータをRSAで暗号化したものです。
"722676e535f86ffc29ba1cafb9856d98d1f697a83b0afc5bb143e2cf2242152a351081fb837192da3e3b2d9021fab75ce32677b6299a24d15e28db883adb36c5fe448d5eb47014f6d2e72eff389f0176efced60380450c87e2015a8c5de6aa90dc8f105683ac5fd96dc33d4d63da62818facda595910cf9aee10f36fe54d4a6a"

NetBIOSUでエンコードされたメタデータをデコードするPythonの実装。
図 14. NetBIOSUエンコードをデコードするPythonスクリプト

マスクエンコードとデコード

マスクエンコードアルゴリズムはMalleable C2プロファイルのほかのエンコードアルゴリズムに指定して組み合わせで使えます。その内容をTeamServerがロードしてC2通信として使うことができます。Beaconはランダムな4バイトをマスクのXORキーとして生成します。次に、生成したマスクキーで、暗号化した128バイトのメタデータをXORし、マスクキーと暗号化データをC2通信のためにTeamServerに送ります。例として randomized.profileの内容を順を追って説明します。

1. 図15はメタデータをマスクとBase64URLでエンコードしたプロファイルの一部を示しています。このプロファイルではURIとメタデータのエンコードアルゴリズムをマスクとBase64URLと定義しているので、エンコードされたメタデータはURIにアペンドされます。

メタデータをマスクとBase64URLでエンコードしたプロファイルの一部を示したもの。このプロファイルではURIとメタデータのエンコードアルゴリズムをマスクとBase64URLと定義しているので、エンコードされたメタデータはURIにアペンドされます。
図 15. ランダム化されたプロファイルのメタデータエンコードオプション

2. HTTP C2トラフィック

図16は図15のプロファイルに基づくC2トラフィックなので、次の手順でエンコードデータを元に戻せます。

  • キャプチャしたトラフィックから、全体のURIが/zChN7QMDhftv10Li9Cu-fm_T_3qDQawT-Z1GzNg1FWfAfSILT-u_rKLvXP-RE0ac-pxJTlGFCUIm4Aw9rGHPCIJVl0zNdCbM_G2VkYXJ5GGtVh8LWM4YLGZD9okLcFBc402j5zESK71HaR_owJb-AVBfFvAo8q0I2J74rmfGyIROygであることがわかります。
  • 接頭辞の/zCを取り除きます。残りの値はBase64URLでエンコードされています。
    hN7QMDhftv10Li9Cu-fm_T_3qDQawT-Z1GzNg1FWfAfSILT-u_rKLvXP-RE0ac-pxJTlGFCUIm4Aw9rGHPCIJVl0zNdCbM_G2VkYXJ5GGGtVh8S0LWMM4YLGZD9okLcFBc402j5zESK71HaR_owJb-AVBfFvAo8q0I2J74rmfGyIROyg
図15のプロファイルに基づくC2トラフィック。本文で詳しく説明した手順でエンコードデータを元に戻せる。
図 16. ランダム化されたプロファイルに基づくC2トラフィック

3. データのエンコードとデコード

  • Base64URLのエンコードとデコード Base64URLエンコードされたデータ:
    hN7QMDhftv10Li9Cu-fm_T_3qDQawT-Z1GzNg1FWfAfSILT-u_rKLvXP-RE0ac-pxJTlGFCUIm4Aw9rGHPCIJVl0zNdCbM_G2VkYXJ5GGGtVh8S0LWMM4YLGZD9okLcFBc402j5zESK71HaR_owJb-AVBfFvAo8q0I2J74rmfGyIROyg
  • Base64URLデコードされたデータ: 84ded030385fb6fd742e2f42bbe7e6fd3ff7a8341ac13f99d46ccd8351567c07d220b4febbfaca2ef5cff9113469cfa9c494e5185094226e00c3dac61cf088255974ccd7426ccfc6d959185c9e46186b5587c4b42d630ce182c6643f6890b70505ce34da3e731122bbd47691fe8c096fe01505f16f028f2ad08d89ef8ae67c6c8844eca0 図17に示したコードのように、PythonのBase64ライブラリを使ってBase64URLでエンコードしたデータをデコードすると、デコードされた16進データの長さは132で、最初の4バイト(84ded030)がマスクのXORキーです。残りの128バイトは、マスクのXORアルゴリズムでエンコードされたメタデータです。PythonコードでのBase64URLデコードを以下に示します。
Python Base64ライブラリでBase64URLエンコードされたデータをデコードする。
図 17. Base64URLデコードを行うPython3のコード
  • マスクのエンコードとデコード: マスクのキーは84ded030です。マスクエンコードしたデータは以下のようになります。385fb6fd742e2f42bbe7e6fd3ff7a8341ac13f99d46ccd8351567c07d220b4febbfaca2ef5cff9113469cfa9c494e5185094226e00c3dac61cf088255974ccd7426ccfc6d959185c9e46186b5587c4b42d630ce182c6643f6890b70505ce34da3e731122bbd47691fe8c096fe01505f16f028f2ad08d89ef8ae67c6c8844eca0マスクデコードしたデータ:
    bc8166cdf0f0ff723f3936cdbb2978049e1fefa950b21db3d588ac3756fe64ce3f241a1e71112921b0b71f99404a3528d44af25e841d0af6982e5815ddaa1ce7c6b21ff65d87c86c1a98c85bd1591484a9bddcd10618b40fec4e67358110e4eabaadc1123f0aa6a17a52d95f64cbd5c1ebdc5f1a545359df0e38ac5c0c9a3c90

    図18のPythonコードでマスクエンコードしたデータをデコードすると、デコードされた16進データの長さは128バイトになります。この128バイトはRSAアルゴリズムで暗号化されたメタデータで、詳細はちかく公開予定のブログで解説します。

    マスクデコードを行うPythonコード:

このPythonコードはMaskエンコードしたデータのデコードに使える
図 18. マスクデコードを行うPython3のコード

実際の攻撃事例

以下のセクションでは、実際にマルウェアによる使用が確認された、2つの異なる事例でのCobalt Strikeペイロードを紹介します。1つめの事例ではBase64エンコードが使われ、2つめの事例ではBase64URLエンコードが使われています。パロアルトネットワークスはAutoFocusシステムのUnit42.CobaltStrikeタグ以下で静的・動的分析によりこれらのペイロードを特定しました。

Base64エンコード

SHA256: 6b6413a059a9f12d849c007055685d981ddb0ff308d6e3c2638d197e6d3e8802

マルウェアによるCobalt Strikeの利用実例。この事例ではメタデータがBase64でエンコードされている。
図 19. Base64エンコード

Base64URLエンコード

SHA256: f6e75c20ddcbe3bc09e1d803a8268a00bf5f7e66b7dbd221a36ed5ead079e093

マルウェアによるCobalt Strikeの利用実例。この事例ではメタデータがBase64URLでエンコードされている。
図 20. Base64URLエンコード

結論

Cobalt Strikeは侵害後のアクターをエミュレートする強力なツールです。上記の5つのエンコードアルゴリズムは巧妙で、セキュリティ検出回避をねらって設計されています。セキュリティアプライアンス単体ではCobalt Strikeの攻撃を防げないので、ファイアウォール、サンドボックス、エンドポイント、さらにこれらすべての要素を統合してくれるソフトウェアのセキュリティソリューションを組み合わせて使うことが必要になります。

パロアルトネットワークスのお客様は、次の方法でこの種の攻撃から保護されています。

  1. 脅威防御シグネチャ86445と86446を含む次世代ファイアウォール(NGFW)は、デフォルトプロファイルのBase64メタデータエンコードを行うHTTP C2リクエストを識別します。
  2. NGFW用のセキュリティサブスクリプションWildFireCortex XDRはCobalt Strike Beaconを識別・ブロックします。
  3. AutoFocusをお使いのお客様は次のタグを使用してこれらのアクティビティを追跡できます: CobaltStrike

IoC (侵害指標)

Cobalt Strike サンプル

  • 6b6413a059a9f12d849c007055685d981ddb0ff308d6e3c2638d197e6d3e8802
  • f6e75c20ddcbe3bc09e1d803a8268a00bf5f7e66b7dbd221a36ed5ead079e093

Cobalt Strike Beacon サンプル

  • /n9Rd
    • SHA256ハッシュ:
      • fc95e7f4c8ec810646c16c8b6075b0b9e2cc686153cdad46e82d6cca099b19e7
  • /flas
    • SHA-256ハッシュ:
      • 11b8beaa53353f5f52607e994849c3086733dfa01cc57fea2dae42eb7a6ee972

Cobalt Strike TeamServerのIPアドレス

  • 80.255.3[.]109
  • 143.244.178[.]247

追加リソース

Cobalt Strike Training (Cobalt Strikeトレーニング)
Cobalt Strike Malleable C2 Profile (Cobalt Strike Malleable C2プロファイル)
Cobalt Strike解析&チュートリアル: Malleable C2プロファイルでCobalt Strike検出が難しくなる理由
Cobalt Strike Attack Detection & Defense Technology Overview

Enlarged Image