ファイル共有(交換)ソフト「Winny(ウィニー)」のネットワークを介して拡散するウイルスにより、日本では深刻な情報漏えいが相次いでいます。米国でもこれら一連の事件はいろいろなメディアで報道されており、日本のインターネット社会が非常に深刻な事態に陥っているという認識が広まりつつあります。

 私が所属する米eEye Digital Securityでも、遅ればせながらWinnyに関する本格的なリサーチを数週間前に開始しました。具体的には、Winnyのコード解析やWinnyネットワークの分析を通して、情報漏えいを防止するための手段など、Winnyにまつわる様々な事柄についてリサーチを進めています。後述するように、検出ツールも開発および公開しました。これらについては、主に私ともう一人の日本人エンジニアの金居が担当しています。

 今回のリサーチやツール開発に関連した話題として、今回はWinnyを検出する方法についてお話したいと思います。現在はWinny Ver.2が主流ですので、Ver.2について解説します。リサーチでは検出方法以外にも、興味深い結果が複数得られていますので、それらについても「ITpro Watcher」で今後解説したいと考えています。

Winnyが動作するPCを検出する

 Winnyが動作するホストをリモートから検出する方法は、大きく分けて3通りあります。

 1つは、リモート・ホストのファイル・システムにアクセスして、Winny本体、もしくはWinnyの設定ファイルを検索するという方法です。この方法は、Winny本体が起動していなくてもその存在を検出できるというメリットがあります。

 ただ、ファイル・システムへのアクセスにネットワーク・ドライブを利用した場合、検査に時間がかかるというデメリットがあります。特に、検査対象ホストの数が多い環境では、検査に膨大な時間がかかります。そのような場合は、各マシンにファイル・スキャナをインストールして実行することになります。いずれにせよ、リモート・ホストのファイル・システムに対するアクセス権が必要となります。

 2つ目は、リモート・ホストに対してポート・スキャンを行い、Winnyプロトコルでサービスを提供しているポートの有無を調べるという方法です。この方法は、前述したファイル・スキャンに比べて非常に高速です。

 また、リモート・ホストのファイル・システムにアクセスする必要はありませんので、それらへのアクセス権は不要です。Winnyが利用しているポートにさえアクセスできれば、その存在を確認できます。ただし、プロトコル検出に基づいた手法ですので、当然ながらWinnyが起動していないと検出できません。

 3つ目は、ネットワークを流れるパケットをモニタリングして、Winnyを受動的に検出するという方法です。上記二つの方法とは異なり、この方法ではホストに対してアクティブにスキャンを行う必要がありません。ルーター直下のハブのミラー・ポートなどでモニタリングすれば、ネットワーク内にWinnyユーザーが存在するかどうかを確認できます。

 また、各ホストに対する特別なアクセス権も不要です。さらに、検出されたWinnyセッションに対してkillパケットを飛ばすなどすれば、ネットワーク内におけるWinnyの利用を制限することも可能です。

 しかし、この手法もプロトコル検出に基づいていますので、Winnyが起動していないと検出できません。加えて、ルーターの内側で、そのルーターに出入りするパケットすべてをモニタリングできることが前提となります。

 リモート・ホストのファイル・システムにアクセスする最初の方法を用いたスキャナについては、いくつかのアンチウイルス・ベンダーがリリースしています。eEyeで、以下の二つのファイル・スキャナをテストしました。その結果、両ツールとも非常に精度良くWinnyを検出できました。

・アンラボ「ウィニーワクチン」
・シマンテック「Winny 検索ツール」

 2番目および3番目の手法を用いたスキャナについては、eEyeが一般に無償配布しています(関連記事)。「Winny Scanner」と「Winny Monitor」です。詳しくは、以下のサイトを参照ください。

・住商情報システム「eEye Digital Security Products」


Winny Scanner
[画像のクリックで拡大表示]

Winny Monitor
[画像のクリックで拡大表示]

 そのほか、Active Directoryのグループ・ポリシーでWinnyの実行を禁止する方法もあります。管理対象システムにあらかじめインストールして利用する、いわゆる「エージェント・タイプ」のWinny検出・対策のツールも各社からリリースされています。

 いずれの検出・対策手法にも一長一短があるので、必要に応じてこれら手法を組み合わせるなどし、効果的に組織内のWinnyを検出・遮断できるような仕組みを構築するとよいでしょう。

Winnyの暗号は簡単に解読できる

 ご存じの方も多いと思いますが、Winnyパケットは「RC4」と呼ばれるアルゴリズムで暗号化されています。このため、パケット・モニターでその内容を確認しても単なる乱数の羅列にしか見えず、Winnyパケットの特徴を見出すことはできません。

 また、利用するポート番号には、Winnyが起動した際にランダムな番号が割り振られるので、ポート番号で検出することもできません。利用するポートがランダムである以上、プロトコル検出を行う必要があります。そのためには、暗号の解読が必要不可欠となります。


暗号化されているWinnyパケット
[画像のクリックで拡大表示]

 とはいえ、Winnyの暗号は単純であり、簡単に解読できることは周知の事実となっています。Winnyのノード間通信で利用されている暗号アルゴリズムは共通鍵暗号方式のRC4ですので、共通鍵はパケット、もしくはコード中に必ず存在することになります。これは、コード解析されないことが前提となっている仕様であり、暗号通信としては脆弱なものです。

【4月12日追記】4月12日にいただきましたコメントにありますように、上記パラグラフ(「とはいえ」から「暗号通信としては脆弱なものです。」まで)には誤解を招く表現がございました。つきましては、以下の表現(「とはいえ」から「至らなかったようです。」まで)に変更いたします。【以上、4月12日追記】

【4月12日変更分】

 とはいえ、Winnyの暗号は単純であり、簡単に解読できることは周知の事実となっています。Winnyのノード間通信には認証がなく、また、利用されている暗号アルゴリズムは共通鍵暗号方式のRC4のみです。

 このため共通鍵は、動的に生成されたものがそのまま相手ノードに送られているか、あるいはコード中に記述されているということになります。これは、コード解析されないことが前提となっている仕様であり、暗号通信としては脆弱なものです。RC4を利用していることが問題ではなく、鍵が安全に管理・受け渡しされていないことが問題です。

 しかし、公開鍵暗号を共通鍵の受け渡しに利用する場合、鍵ペアを使い回すと、公開鍵がノードのユニーク情報になってしまい匿名性が損なわれます。匿名性を保ちつつ公開鍵暗号方式で安全に共通鍵を受け渡しするような検討がなされていたようですが、結局実装には至らなかったようです。

【以上、4月12日変更分】

 一応、パッカーによるコードの難読化やデバッガ検出などのリバース・エンジニアリング対策を施して、そのままでは実行ファイルを解析できないようにしています。しかし、アンパッキングやデバッガ検出の無効化もさほど難しくはないので、「Winnyパケットの暗号は既に解読されてしまっている」といってよい状況になっています。

 前述のように、暗号化されたままではWinnyパケットの特徴を見出せません。しかし解読さえすれば、Winny通信には特徴があることが分かります。その特徴からWinnyを検出できます。具体的には、Winnyが送出する「初期鍵パケット」の有無を調べることで、Winnyのトラフィックを検出することができます。

 初期鍵パケットのパケット長は11バイトで、以下のようなフォーマットになっています。


初期鍵パケットのフォーマット

 そして、初期鍵パケットの7バイト目以降には以下の値が入っています。

01 00 00 00 61

 つまり、ブロック長は先頭4バイトの"01 00 00 00"(1バイト)、ブロック・データは"61"('A')となっています。この部分は暗号化されているので、そのままではこのような値になっていません。同じ初期鍵パケットに含まれる「暗号キー」で復号する必要があります。

 具体的には、以下のような手順となります。Winnyのファイル転送ポートにTCP接続すると、この初期鍵パケットがWinnyホストから送信されます。例えば、以下のようなデータが流れてきた場合、暗号キーは"76 CA DF 6C"となります。

DA 29 76 CA DF 6C 91 D9 71 8F 13

 この4バイトを、RC4の鍵初期化関数(rc4_init)に入力します。

rc4_init(&rc4key, "\x76\xCA\xDF\x6C", 4);

 そして、この関数の出力結果を鍵にして、暗号キー以降の5バイト"91 D9 71 8F 13"を復号します。

rc4_crypt(&rc4key, "\x91\xD9\x71\x8F\x13", p_decrypt, 5);

 その結果(p_decrypt)が「01 00 00 00 61」になった場合には、そのパケットはWinnyの初期鍵パケットであると判断できます。Winny ScannerやWinny Monitorは、このパケットを利用してWinnyを検出しています。

 2パケット目以降は、この暗号キーをベースにした新たなキーを作成し、パケットを復号します。キャッシュ・ファイル処理、ファイル名処理、バージョン番号処理などにおいても、特別なキーを使ったり特殊な演算を施したりするなどして、解読を少しでも難しくするようにしています。いずれ、これらの暗号についても解説したいと思います。

「Winnyネットワーク分析システム」を実装

 Winnyプロトコルを利用すれば、Winnyネットワーク内のノード情報(IPアドレス、ポート番号、クラスタリング情報など)を収集することができます。また、キー・パケットの収集により、特定ノードが持つファイル一覧や、特定ファイルを持つノード一覧なども取得できます。

 このような仕組みを実現するWinnyネットワーク分析システムは既に実装が完了しており、今後、何らかの形で一般に無償配布できればと考えています。その他、漏洩してしまった情報の追跡や消去を支援するためのツール群も開発中です。こちらもあわせて無償配布したいと考えています。

 その他、Winnyのリサーチを通していくつかの興味深い結果が得られています。情報漏洩対策などに有効利用できる結果については、詳細を随時公表する予定です。また、ソフトウエアとして実装し、そのソフトウエアを公開していきたいとも考えています。

 分析システムの詳細な仕組みや実装については、折を見てここでお話したいと思います。また、5月12日に「Inside Winny」と題して、Winnyの解析とそのセキュリティ脅威分析について講演する予定です。興味がございましたらぜひご参加ください。同セミナーの詳細は、住商情報システムの「eEye Digital Security Products」ページに掲載しております。