ネットワーク内の複数のコンピューターを標的にした攻撃において、ラテラルムーブメントは重要な意味をもつフェーズの1つです。

ラテラルムーブメントでは通常、リモートコードの実行を可能にする既存のメカニズムが悪用されます。ここでは、攻撃者が正規の認証情報を所有していることが前提になります。

これらのメカニズムは通常どれも正規の理由で使用されるものですが、多くの環境では、それらが悪用されていないかどうかを監視しています。リモートサービスが滅多に利用されることがないネットワークでPSExecツールが使用されているといったように、特定の環境で通常使用されることがないベクターを介してコードがリモートで実行されている場合、このような操作は異常であるとして検知され、悪意のある操作としてフラグが付けられます。

攻撃に長けたハッカーが好んで用いる手法には、悪意のあるそれと類似した正規の行動パターンが絶えず発生して相手に検出されにくいリモート実行のテクニックや、防御側があまり監視することのない実行チャネルを悪用したテクニックがあります。

以上の理由から、攻撃者は用いるラテラルムーブメントの攻撃手法の数を増やしており、これにより、自らを偽装して検知を逃れる方法を確立しています。

このブログでは、サイバーリーズンが発見した新しいラテラルムーブメントの手法について説明します。このテクニックは、WMI(Windows Management Infrastructure)を悪用しています。さらに、すでに広く知られているラテラルムーブメントの手法についても詳しく説明します。

新しい手法はまだあまり知られていないため、多くのセキュリティツールがこれを検知できません。しかし、サイバーリーズンが開発したツールでは、技術者によるその事前検証において、新しい手法でハッカーのできることが明らかになっています。詳細はこちらの資料に記載されているPowerShellのスクリプトを参照してください。

ラテラルムーブメントに悪用される正規の機能について、詳細がこちらの記事にまとめられています。是非ご覧ください。この記事では、Distributed Component Object Model(DCOM)による攻撃の手法について説明しています。

WMIの概要

Windows Management Infrastructure(WMI)は、Windows OSおけるWBEM標準とCIM標準の実装環境です。このインフラストラクチャでは、ユーザー、管理者、開発者、そして攻撃者は、OS内のさまざまな管理対象コンポーネントについて、列挙、操作、対話の処理が可能です。

実際のところ、WMIは、抽象化されたオブジェクト指向の統合モデルを提供します。このモデルには、個々のマシンに関する独立した多くの要素を表すクラスが含まれています。

また、このモデルでは、関連のない多くのAPIと直接やり取りをしたり、これらAPIのドキュメントを確認したりする必要はありません。

WMIには、システムレジストリ、プロセス、スレッド、ハードウェアコンポーネントなどの要素を表すクラスが含まれています。

WMIでは、SQLに類似した言語のWQLでWMIクエリを記述して発行するか、PowerShell CIM/WMIコマンドレットのような抽象化機能を利用すれば、クラスごとにコンポーネントのインスタンスを列挙できます。また、クラスやインスタンスに関するメソッドを呼び出すことも可能であるため、基盤となる管理対象コンポーネントをWMIインターフェースから操作することができます。

さらに、WMIの重要な機能の1つに、DCOMまたはWinRMのプロトコルを通じてリモートマシンのWMIモデルとやり取りができる機能があります。攻撃者はこの機能を利用して、リモートマシン上のWMIクラスを遠隔で操作できます。任意のコードをリモートマシン上で事前に実行する必要はありません。

WMIのメインコンポーネント

WMIは以下に示す3つの主要なコンポーネントから構成されています。

  • WMIサービス(winmgmt)はクライアントとWMIモデル自体のあいだでメディエーターとして機能し、クライアントプロセスからのあらゆるリクエスト(例:メソッドコールやクエリなど)を処理します。ほとんどのリクエストの場合、このサービスは、自身では実際の処理ができません。リクエストをほかのコンポーネントに渡して処理させ、その結果を受け取ってクライアントに返します。
  • WMIプロバイダーは、クラス、インスタンス、メソッドを実装した実際のコードが導入される場所です。このプロバイダーはほとんどの場合、インプロセスCOMオブジェクトとして実装されます。
  • WMIリポジトリはWMIモデル用の一元化されたストレージエリアです。プロバイダーによって動的に生成されるインスタンスとは異なり永続性を必要とする要素(クラスの定義やオブジェクトのインスタンスなど)を格納します。

次に、WMIによる古典的なラテラルムーブメントの攻撃手法の観点からWMIについて説明します。

ここでは、ローカルまたはリモートのクライアントは、「Win32_Process」の「Create」メソッドの呼び出しを試みます。このアクションのリクエストはWMIサービスに送られ、リクエストを受け取ったWMIサービスはリポジトリに問い合わせを行い、CIMWin32として呼び出すプロバイダーを特定します。

そして、WMIサービスはリクエストをプロバイダーに転送します。プロバイダーは新たにプロセスを作成し、サービスに対応したプロセスを表すWin32_ProcessインスタンスをWMIサービスに返します。そして、WMIサービスはこのインスタンスをクライアントに渡します。こちらのホワイトペーパーでは、セキュリティおよびフォレンジックの観点からWMIについて詳しく説明しています。是非ご覧ください。

ラテラルムーブメントを実行するためのこの手法は現在では広く知られており、多くの製品でこれを検知できるようになっています。このように従来のテクニックが普通に知られるようになったことを受け、攻撃者はラテラルムーブメントの新たな手法の開発に乗り出し、そこで目を付けたのがWMIでした。

WMIを使用したラテラルムーブメントの新たな手法

派生クラス

厳密に言えば、このラテラルムーブメントの手法は新しいものではありません。しかし、この検知回避の手法を使えば、攻撃において、Win32_Process::Createメソッドと直接やり取りする必要がなくなります。

このメソッドは監視されていることが少なくありません。攻撃者は(リモートで)クラスを作成し、Win32_Processなどのようなすでに問題があるとわかっているクラスからこのクラスへと情報を引き継ぎます。そして新たなクラスのメソッドを呼び出すか、このクラスのインスタンスを作成します。疑わしいとされた旧来のクラスを、これらの作業において直接呼び出す必要はありません。手順は以下のようになります。

  • Win32_Process、Win32_NotEvilAtAllのサブクラスを作成します。これは、WMIを介してリモートで行われます。
  • 新しいクラスが親のメソッドをすべて継承します。
  • 新しく定義したクラスの「Create」メソッドを呼び出します。

このブログ記事で紹介したInvoke-WmiLmスクリプトの抜粋。「Derive」と「Put」のメソッドでリモートマシン上にWin32_Processのサブクラスを新規作成し、新たに定義したクラスのCreateメソッドを呼び出しています。

WMI-Activity ETWプロバイダーのイベントを確認します。一見すると、Win32_Processの直接使用は回避できたように見えます。この様子を以下に示します。

WMIサービスに対するリクエストを示すイベント11のインスタンスにはどれも、WIn32_Processクラスの存在を示す痕跡は確かに見当たりません。検知を逃れる方法として大いに見込みがありそうですが、しかしよく確認してみると、以下のように完全に足跡を消し去ることができていないとわかります。

この場合、なぜ、「Win32_Process::Create」が表示されるのでしょうか。

同じ「Create」メソッドで新しいクラスを作成しても実際には、ターゲットのマシンに組み込まれる新しいコードは1つもありません。つまり、このメソッドは、プロバイダーが同じ場合にのみ実行されるのです。WMI-Activityプロバイダーのイベント12には、WMIサービスとWMIプロバイダーとのあいだで行われる通信の様子が示されています。また、リクエストされたメソッドを実際に実行するプロバイダーをサービスが推測した後に行われたメソッドの実行リクエストについても示されています。

検知に対抗するための別のアプローチとして、WMIイントロスペクションという手法があります。WMIでは、包括的なイベントシステムを利用できます。また、WMI自体の監視に非常に役立ついくつかのイベントも公開されています。このようなイベントの1つでは、マシン上で呼び出されたWMIメソッドのすべてを確認できます。

上記のスクリーンショットからわかるように、MSFT_WmiProvider_ExecMethodAsyncEvent_Preで示されているのは、クライアントがリクエストしたメソッドではなく、プロバイダーが実行した実際のメソッドです。つまり、検知を回避するテクニックは効果がないことになります。

このテクニックは、WMIメソッドの呼び出しの隠蔽には効果を期待できませんが、メソッドの使用を必要としないイベントサブスクリプションのようなWMI「攻撃」では非常に大きな威力を発揮します。これは、あらゆるイベントにおいて、オリジナルのクラスの名前のかわりに派生クラスの名前が表示されるためです。

また、WMIクラスの階層を検知回避に悪用する成功率の低い手法として「Class Cloning」というものがあり、これについても試してみました。この手法では、ターゲットのクラスを取得し、新しいクラスを定義して、メンバーと階層のすべてを、ターゲットと共有します。おそらく、新しいクラスがターゲットのサブクラスでない場合には、検知回避の成功率が高まりますが、クローンのクラスに定義されたメソッドの実装をWMIサービスが特定できず、上手く機能しないようです。

WMIに変更を施し古典的なテクニックを使用する

ただ単にテクニックの数を増やすことだけにこだわっても大きな効果は期待できませんが、PSEXECの置き換えなど、一般的なラテラルムーブメントの攻撃でWMIに変更を加えてこれを使用している攻撃者は、ネットワークの監視ソリューションの回避で十分な成果をあげています。このような手法の例のいくつかを以下に示します。

サービスの作成

リモートサービスの作成は、Windows環境における最も一般的なラテラルムーブメントの手法かもしれません。この手法ではしばしばPSEXECツールや、Pass-the-Hashを有効にした実装が使用されます。そして、リモートサービスの作成では、その再実装にWMIが使用できます。

「Win32_Service」クラスは単一のマシン上で動作する単一のサービスです。このサービスでは、Windowsサービスマネージャ(sc.exeツール)の豊富な機能がすべて公開されています。

Win32_Serviceのメソッドを見ると、そのクラスが標的のマシンのサービスを簡単に操作できるようになっていることがすぐにわかります。ラテラルムーブメントでは、作成、起動、停止、削除の一連の操作がよく使用されますが、これらの操作を行ううえで十分なサービスといえます。

このような操作ができるWMIのクラスはWin32_Serviceだけではありません。以下に示すクラスは、相互に入れ替えて使用できます。

  • WIn32_Service
  • Win32_BaseService
  • Win32_TerminalService
  • Win32_SystemDriver

PSEXECやsc.exeなどの一般的なリモートサービス管理ツール環境を使用した場合、DCERPC上においてMS-SCMRプロトコルで通信が行われます。このプロトコルでは、可能な限り最大レベルの暗号化を使用したとしても、ネットワークトラフィックの監視機能を使用すれば、サービスの作成やサービスの起動などの実行されたアクションのタイプが容易に識別できます。


Wiresharkでのキャプチャ画面:sc.exeでリモートサービスが作成される様子

一方、WMIを使った同じアクションでも、ネットワーク上では全く様子が違って見えます。

DCERPCベースで通信を行っていても、すべてのWMI DCOMメソッドのコールを単一のインターフェースで行い、「パケット」プライバシーレベルの暗号化を施せば、ネットワーク監視ソリューションでは、なんらかのWMIメソッドがコールされたということだけしか掴めなくなります。

また、WINRMプロトコルを使用した場合、WMIトラフィックはHTTPのように見え、SVCCTLインターフェースを経由した場合とは完全に違ったものと映ります。これはつまり、WMIに変更を加える手法では、ラテラルムーブメントの検知でベースとなるネットワークトラフィックシグニチャを効果的に欺くことができることを意味します。

旧来のタスクスケジューリングメカニズムの使用

WMIでは、Windowsの旧来のタスクスケジューリングメカニズム(at.exe)とやり取りするための方法も提供されます。このメカニズムは、WIn32_ScheduledJobクラスを使って実行されます。

このクラスでは、クラスインスタンスの列挙を通じて、スケジューリングを施したジョブの作成、削除、列挙ができます。専用のメソッドは使用しません。at.exeユーティリティ自体と同様に、このクラスの機能は、Windows 8以降のOSでは使用できません。タスクを強制的に実行できない場合、古典的テクニックと同様に問題は簡単に克服できます。タスクの登録から数秒後にタスクが実行されるようスケジューリングするだけです。

新しいタスクスケジューリングメカニズムの使用

WMIを用いてラテラルムーブメントによく使われるメカニズムの1つに、新しいWindowsタスクスケジューラがあります。このスケジューラは一般に、schtasks.exeユーティリティで操作されます。スケジューリングされたタスクをこの方法で作成した場合、タスクは、ScheduledTaskProvプロバイダーのPS_ScheduledTask、関係するクラスを使って表記されます。

PS_ScheduledTaskクラスには、スケジューリングされた任意のタスクをカスタムのアクションでクライアントが作成、削除、実行できるメソッドが公開されています。

それどころか、Windows 8以降の環境で使用できる、スケジューリングされたタスクのコマンドレットでは、バッググラウンドでWMIクラスが使用されます。つまり、これらのコマンドを悪用している攻撃者は、意識してあるいは無意識のうちにさまざまなIDSの検知を逃れている可能性があるのです。

なお、新しいタスクスケジューラはWindows 7以降のマシンで利用できますが、ScheduledTaskProvプロバイダーが利用できるのはWindows 8以降のマシンに限られます。この点に注意してください。

WINDOWSインストーラーの悪用

Windows Installerのプロバイダーでは、Win32_Productと呼ばれるクラスが公開されています。このクラスは、Windows Installer(msiexec)によってインストールされているアプリケーションを表します。このクラスでは、悪意のあるmsiパッケージを標的のマシンで実行することができます。

Win32_Productの「Install」メソッドでは、(そしておそらく「Admin」メソッドや「Upgrade」メソッドでも、)パスやURLからmsiパッケージをインストールできます。以下に示すように、Metasploitでは、悪意のあるペイロードを組み込んだパッケージを作成することが可能です。

Metasploitは実行ファイルをmsiファイルとしてパッケージングできます。また、このパッケージフォーマットでは、VBScriptのペイロードやJScriptのペイロードの組み込みも可能であるため、msiを非常に多様なペイロードコンテナにすることができます。

また、あまり成功率の高くないテクニックですがWin32_Productを悪用するものとして、「msiexec /y」コマンドの複製を狙った手法があり、ここでは、コマンドラインからDLLファイルの登録を試みます。しかし、WMIでは、これは不可能なようです。

また、レジストリにあるアンインストーラーのコマンドラインフィールドをハイジャッキングし、WIn32_Productの「Uninstall」メソッドでコマンドを実行しようとしてみましたが、これも上手くいきませんでした。

UninstallStringの値を任意のコマンドラインに変更し「Uninstall」メソッドを呼び出しても、この操作は機能しないようです。

悪意のあるWMIプロバイダーのローディング

すでに述べたように、WMIプロバイダーには、ほとんどのクラスのインスタンスやメソッドが実装されます。これはつまり、カスタムのプロバイダーをロードすれば、コードの実行が可能になることを意味します。

ここ最近のAlexander Leary氏との会話を通じ、WMIの機能だけでWMIプロバイダーをリモートマシンに登録する方法がわかりました。この方法では、前もってコマンドラインを実行する必要がありません。この手法の弱点の1つは、悪意のあるWMIプロバイダーのDLLを実際にマシンに配布、実装しなければならない点にあります。

ここでの目的はWMIプロバイダーとしてコードを正常に機能させることではなく、WMIプロバイダーとしてロードさせることだけなので、任意のコマンドラインをWMIプロバイダーとして実行します。必要な手順は以下のとおりです。

はじめに、COMオブジェクトを作成します。ほとんどの場合、WMIプロバイダーはインプロセスのCOMオブジェクトとして実装されますが、ここでは、任意のコマンドラインを実行したいので、アウトオブプロセスのCOMオブジェクト登録をプロバイダーのベースとして記述します。

次に、プロバイダー自体を登録する必要があります。これを行うために必要なことは、__Win32Providerクラスのインスタンスをリモートマシンに作成する作業だけです。このインスタンスは、登録したWMIプロバイダーを表します。

__Win32Providerのインスタンスには、以下のような重要なフィールドが3つあり、これらを作成します。

  • Name:人が判読できるプロバイダーの名前。後で参照用に使用します。
  • CLSID:新たに作成したCOMオブジェクトのクラスID
  • HostingModel:このフィールドは、COMオブジェクト自体をロードする方法を示します。「NetworkServiceHost」は、COMオブジェクトをライブラリとして、「Network Service」ユーザーの特殊なホストプロセスにロードします。「LocalSystemHost」は、COMオブジェクトをライブラリとして、システムユーザーのホストプロセスにロードします。「SelfHost」は、COMオブジェクトをスタンドアロンの実行ファイルとして、システムユーザーにロードします。任意のコマンドラインを使用したいので、プロバイダーは実行ファイルとして実行します。

通常、プロバイダーは、プロバイダーが実装しているクラスやメソッドの1つがコールされたり照会されたりしたときに要求に応じてロードされます(メソッドやインスタンスのプロバイダーの登録は、__MethodProviderRegistrationや__InstanceProviderRegistrationのクラスを通じて処理されます)。

ただし、今回用意した任意の実行ファイルの場合、そのように動作しないのは明らかです。しかし、ロード対象のWMIプロバイダーを列挙する「MSFT_Providers」クラスには「Load」というメソッドがあり、これによってWMIプロバイダーが要求に関係なくロードされます。

また、COMオブジェクトが実際にWMIプロバイダーを起動したのをOSがはじめて認識したのは、すでにコマンドが実行された後のようです。つまり、明らかに偽のプロバイダーオブジェクトを実行できてしまったというわけです。さて、注意すべきことがあります。

SelfHostホスティングモデルでWMIプロバイダーを登録すると、実際にはアラートがイベントログに書き込まれるのです。これは、注意を払う必要のあるプロバイダーが作成されたことを意味します(この処理はSystemの権限を使って実行されます)。

ログの書き込みを回避するには、NetworkServiceHostOrSelfHostホスティングモデルを使用します。このモデルはまず、プロバイダーをライブラリとしてロードするよう試みます(登録の処理は省略)。

そして、ロードするライブラリが存在せずロードに失敗すると次は、実行ファイルとしてプロバイダーをロードしようと試みます。コマンドラインが提供され、イベントログへの書き込みは行われません。

これまでの説明をまとめる意味で、悪意のあるコマンドラインをWMIプロバイダーとしてロードしてみます。手順は以下のとおりです。

  • 新しいキーをHKLM/SOFTWARE/Classes/CLSID/{SOMEGUID}に作成します(レジストリの操作はStdRegProv WMIプロバイダーで行います)。
  • LocalServer32のサブキーを追加します。「(default)」の値に、実行するコマンドライン(例:PowerShellでエンコードした任意のコマンド)を指定します。
  • __Win32Providerクラスのインスタンスを新規に作成します。この際、CLSIDフィールドはCLSIDに、また、HostingModelはNetworkServiceHostOrSelfHostにします。
  • 新規に作成したプロバイダーの名前で、MSFT_ProvidersクラスのLoadメソッドを呼び出します。
  • リモートで認証付きの処理を実行します。必要以上に複雑に見えますが、まず検知されることのない手順です。

まとめ

ここで紹介したテクニックは比較的知られておらず、一般にほとんどのセキュリティ製品が検知できずにいます。しかし、Windowsでは、これら個々のテクニックを検知するために必要なWMI機能に関する情報が豊富に用意されています。

WMI-Activity ETWプロバイダーとWMIイベントシステムではともに、あらゆるWMIメソッドについて、コール、インスタンス作成、クエリの操作に関する詳細な情報が得られます。これらの情報があれば、注意を向ける必要のあるWMIの機能が呼び出されているかどうかを十分に判断できます。

ここで説明したテクニックはドキュメント化されている正規の機能を悪用していますが、アクション別に監視できるほど頻繁に使われているわけではありません。組織をラテラルムーブメントの攻撃から守るためには、これらのテクニックを理解しておく必要があります。

そして、WMIに関する処理が行われた場合に詳しい情報を把握できるよう、また、ここで説明したものも含め、WMIを悪用する多くのテクニックを阻止できるよう、複数の対応手段を準備しなければなりません。

ホワイトペーパー「すべての組織が狙われている」

企業、組織がどんなにセキュリティを強固にしてもハッカーが悪用できる脆弱性は必ず存在します。侵入されることが避けられないことを受け入れ、新たな対策を立てる必要があります。本書で、なぜ避けられないのか、どのように対処するのかをご覧ください。
https://www.cybereason.co.jp/product-documents/input/?post_id=606

ホワイトペーパー「すべての組織が狙われている」