暗号化を利用してドメイン乗っ取りを防止する W32.Virut
W32.Virut は、Windows ファイルに感染するワームとして、2006 年から確認されています。常に脅威チャートの上位 10 位以内に入っているので、定期的な監視が必要です。
最近の亜種の解析から、ボットとコマンド & コントロールサーバーとの間の通信プロトコルを強化する変更が加えられたことが判明しています。これは、ブラックリストへの登録やシンクホールによる捕捉を防ぎ、コマンド & コントロールサーバーが乗っ取られることを避けるためです。
Virut は、コマンド & コントロール(C&C)サーバーとして機能する 2 つの IRC サーバーのいずれかに接続します(現在これはilo.brenz.pl とant.trenz.pl です)。IRC コマンドは暗号化され、TCP ポート 80 と 443 を経由してトンネリングされるのが普通ですが、これらは HTTP と HTTPS がそれぞれ使うポートです。C&C によって送信されるメインコマンドは、追加のマルウェアをダウンロードしてインストールするようボットに指示します。
このときのドメインがブラックリストに登録、あるいは遮断されている可能性があるので、ハードコードされているドメインに接続できない場合に新しい C&C の候補を探すドメイン名ジェネレータが追加されました。これが 1 つ目の改良点です。この手法は新しいものではなく、猛威を振るった Downadup や Mebroot も含めていくつかのマルウェアによって過去にも使われたことがあります。
ドメインジェネレータは 2 つのシードを利用します。
- すべてのコンピュータに共通すると想定される、現在の日付。
- [0, 99]の範囲のランダムな整数 C。
1 つの整数 C ごとに 100 個のドメインが、[アルファベット 6 文字].com という形で生成されるので、全体では毎日 10,000 個のドメインを生成できることになります。100 個ずつという区切りがあるため、すべてのボットを移行するには、オペレータが 100 個のドメイン(1 区切りごとに 1 つ)を登録しなければならないという不便さがあります。一方、マルウェアコントローラには、大量のドメインを遮断しなければボットと C&C との通信をすべて阻止することはできないという大きな強みがあります。
自動生成されたドメインが、何らかの無関係な第三者によってすでに登録されていた場合、Virut は最初の検証ステップを実行し、そのサーバーが Virut の C&C かどうかを確認します。サーバーへのクエリーは、TCP ポート 443 を介して行い、256 バイトの長い BLOB データが返されると想定します。このデータはドメイン自体の、署名された SHA-256 ハッシュです。ボットは、そのコードに埋め込まれている 2048 ビット RSA 公開鍵を使ってこの BLOB を復号化します。したがって、秘密鍵の所有者以外が、ドメインの認証に使われる署名済み BLOB を生成することはできません。
図 1: Virut で使われる RSA 公開鍵を表すアセンブリコード
ボットと C&C 候補の間で自身の認証のために行われる交換の概略を、次の図に示します。
図 2: ドメインの生成と検証
ただし、この検証は Virut 以外のサーバーに誤って接続することを避けるのが主な目的であることに注意してください。この検証によって、Virut コントローラがドメインを使う前であればドメイン乗っ取りは防止されますが、サーバーが C&C として使われた後には、署名済みのドメインハッシュを簡単に再生できるので、ドメイン乗っ取りは防止されません。
こうして、Virut の作成者はドメイン乗っ取りを防ぐために追加のチェックを実装する必要に迫られました。新しい亜種は、認証の目的で C&C に 30 秒間の時間を確保します。認証に成功した場合、ボットはサーバーから送信されたコマンドを受け取って処理し、成功しなかった場合には接続が終了されます。
- まず、ボットはサーバーのタイムスタンプと署名済みデータ BLOB を含む PRIVMSG コマンドを待ちます。
- 署名済み BLOB には、暗号化されたタイムスタンプと暗号化されたサーバーの IP アドレスが記録されています。
- RSA 公開鍵を使ってボットが BLOB を復号化すると、復号化されたタイムスタンプと IP アドレスは平文のタイムスタンプと現在のサーバーの IP アドレスに一致すると想定されます。
- これが一致しない場合は、認証に失敗します。
- 一致する場合は、ボットが返されたタイムスタンプを自身のシステム時刻と照合します。サーバーのタイムスタンプが、前後 3 日間の範囲にあれば、認証は成功と見なされます。
これでチャレンジ/レスポンスのメカニズムは単純で安全になったかもしれませんが、Virut の実装は複雑になり欠陥が生じます。
署名済みのタイムスタンプは、認証方式に対するリプレイ攻撃を避けることが目的でしたが、前後あわせて 6 日間も誤差が許容されるのであれば、誰にでもダウンロードと実行のコマンドを発行する時間的余裕があることになり、コマンドの暗号化が対称式でしかない以上、ボットネットは乗っ取られる可能性があります。Virut の作成者は、セキュリティ向上の目的で BLOB にサーバーの IP アドレスを追加することにしたと推測するしかありません。実際、DNS を乗っ取って同じ IP アドレスを使うのは困難ですが、それでも万全の防御とは言えません。しかも 6 日間という時間の余裕が悪用される可能性もあります(注意: BLOB 検証ルーチンのアセンブリ実装は寄せ集めのようです。検証後に 4 バイトの追加チェックが実行されていますが、これは IP アドレスチェックに対応するために追加された可能性があります。これは、図 1 の「extra DWORD check」で始まる行からわかります)。
まとめ
悪質なプログラムでは、非対称の暗号化が使われることがますます増えていますが、その用途は実に多様です。たとえば、ホストの認証、ペイロードの検証、対称式の暗号化キーの保護(一部のランサムウェアで使われている)などに利用されているほか、標的型攻撃の場合にはきわめて強力な不明瞭化の仕組みとしても使われる可能性があります。
ウイルス対策業界の立場から言えば、非対称の暗号化は疫病のようなものですが、アルゴリズムそのもの以上に、プロトコルと実装方法が大きくその出来を左右します。Virut の場合、最終結果は実効的かもしれませんが、プロトコルは不確実です。実装についても、その不手際がマルウェア作成の打破につながることが多いので、そう期待したいところです。
* 日本語版セキュリティレスポンスブログの RSS フィードを購読するには、http://www.symantec.com/connect/ja/item-feeds/blog/2261/feed/all/ja にアクセスしてください。