では,IDSはどんな方法で,危険な通信を判断しているのか。Part2では,その検知方法について,詳しく解説していこう。
実際に,IDSではどのように「危険」な通信を判断しているのか,その検知方法についても確認しておこう。
危険な通信を検知する方法は2種類
検知方式は大きく二つある。一つは「シグネチャ型」と呼ばれるもので,もう一つは「アノマリ型(異常検知型)」と呼ばれているものである(図1)。
従来から広く利用されてきた伝統的な方式はシグネチャ型で,パターン・マッチングによって通信パケット内に不正なビット列などが入っていないかを調べる。この方式では,不正なものをあらかじめルールとしてデータベースに登録しておく。これが「シグネチャ」と呼ばれるものである。そして,IDSのセンサーがキャプチャしたパケットの中身をシグネチャの情報と比較して一致するものがあれば,不正パケットだと判断を下す。
この場合,許されないものを個別に定義していくので,常にシグネチャを更新する必要がある。新たなぜい弱性が報告され,これに対する攻撃手法が明らかになれば,すぐにこれに対応したシグネチャを追加する必要があるわけだ。昨今のように,毎月どころか毎日のように新たな攻撃手法が明らかになる状況では,この作業は果てしなく,終わりの見えないものになる。
これに対してアノマリ型は,正常というものは変化しないという点に注目している。シグネチャ型のように不正を個別に登録しているのではない。許すものは何か,つまり「正常とは何か」を定義し,それに違反するものはすべて異常だと判断する。例えば,RFCに準拠していることをもって正常と定義したら,この正常という物差しは余程のことが起こらない限り変化しないだろう。ただ,新しいプロトコルが出てきたときなどは,それに対応した物差しを作らないと,異常だと判断してしまう。アノマリ型だけで,すべてをカバーするのも無理があるのだ。
従来,シグネチャ型とアノマリ型の二つの方式は,相反するもののように扱われてきた。しかし,最近では各社のIDS製品でこの両方の方式をミックスさせ,お互いの方式を補完し合うことで,より優れた検知を実現するアプローチが採用されつつある。
シグネチャ型検知の実例
実際にパターン・マッチングに使う「シグネチャ」とはどのようなものなのか,簡単な例を挙げて確認しておこう。
シグネチャは,基本セットをベンダーが用意してくれている。通常の運用であれば,これで対応できることが多い。しかし,ユーザー自身がシグネチャをカスタマイズしたり,新規に作成することもできる。そのためにシグネチャは書き換えや追加が容易な言語で記述できるようになっている。その記述形式は製品によって異なるが,ここでは比較的理解しやすいSQLライクなシグネチャを例に挙げよう。
以下に示した例は,FTP通信でGuestというユーザー・アカウントがアクセスしてきたことを検出するためのシグネチャである。
SELECT Protocol[TCP] AND
Port[21] WHERE Contains["Guest"]
これは,TCPのポート番号21番に対するアクセスがあり,その中身に「Guest」という文字列が含まれていた場合に「不正」と判断することを示している。
また,ディレクトリ・トラバーサルという有名な不正アクセス手法を検知するシグネチャは以下のようになる。
SELECT Application[HTTP] WHERE Contains[../..]
アプリケーション・プロトコルがHTTPで,その中身に「../..」という文字列が含まれていた場合に「不正」と判断することを示している。「..」とは,UNIXなどのOSで上位階層のディレクトリへ移動することを示す記述である。「../..」とは二つ上のディレクトリへの移動を試みていることを意味する。このような上方へのディレクトリ移動は,通常のWebサーバーでは許されていないため,これを不正として検出する。
このようなパターン・マッチングのルールをデータベース化したものがIDSには通常500~1500種類程度登録されている。センサー部分が通信パケットをキャプチャすると,このデータベースの中身と照合して一致すると不正パケットと見なすのである。
アノマリ型検知の実例
アノマリ型には,シグネチャのようにユーザーが独自に作成したりカスタマイズできるような記述形式はない。それは,先にも述べたように,変化に対応し,ルールを逐一追加していく作業が基本的に不要だからだ。
アノマリ型は「正常とは何か」を定義することによって,これに反するものをすべて異常として検出する。例えば,パスワードの入力フィールドに,正常ではASCII(アスキー)文字しか入っていないはずである。人はキーボードからASCII文字しか入力できず,パスワードは人が入力するものなのだから当たり前である。したがって,ASCIIコードの文字が入っているということをアノマリ型では正常として定義し,それ以外のものがパスワードの入力フィールドに入っていたら異常だと判断する。
また,認証の失敗が繰り返された場合などは,あるしきい値を設定して,それ以上間違えた場合は異常とする例もある。これも,「人間は(例えば)3回以内で自分の正しいパスワードを入力できる」という正常値を定め,これに違反するものを異常として検知するのである。
二つを組み合わせて弱点を補う
二つの検知方式の違いを明確にするために,もう一つ例を挙げておこう。以下は,CodeRed(コードレッド)の攻撃パケットの中身である。
GET /default.ida?XXXX…XXX%u9090%u6858%ucbd3
%u7801%u9090%u6858%ucbd3%u7801%u9090%u6858
%ucbd3%u7801%u9090%u9090%u8190%u00c3%u0003
%u8b00%u531b%u53ff%u0078%u0000%u00=a
これを検知するための非常に簡単なシグネチャは,例えば以下のようになる。
SELECT Application[HTTP] WHERE Contains[.ida?]
この場合,プロトコルがHTTPで,その中に「.ida?」という文字列が含まれていた場合に不正と判断される。
これに対してアノマリ型の場合は,HTTPのGETゲットリクエストに続く文字列があまりにも長い場合は異常と判断する。つまり,GETリクエストに続く文字列の正常とは何文字以下かを定義しておき,これを逸脱するものはすべて異常とみなす。
ただ,この「何文字以下なら正常」と定義するのは難しい。RFCをはじめ,どこにも明確な決まりが書かれていないからである。通常,このようなしきい値を決める問題は,それまでの通信パケットを分析した統計値を使うことが多い。つまり,アノマリ型は統計的手法を応用した検知方式でもある。