はじめに

Snort は、強力なオープンソースのネットワーク侵入検知システム(NIDS)です。その最大の特徴の一つは、柔軟なルールベースの言語であり、セキュリティ専門家が悪意のあるネットワーク活動に対するシグネチャを定義できる点にあります。

ルールは、理論と検知をつなぐ架け橋です。「ポートスキャンは疑わしい」といったセキュリティ上の概念も、エンジンが実際のトラフィックに対して評価できる形式で表現して初めて、実用的なものとなります。したがって、ルールの構文を学ぶことは、単に Snort そのものを学ぶ以上の意味を持ちます。それは、防御者がどのようにして振る舞いを機械可読なロジックへと変換するかを学ぶことなのです。

この実験では、カスタム Snort ルールの核心となる構文と構造を学びます。アクション、プロトコル、IP アドレス、ポート、オプションを定義する基本的なルールを作成し、特定の ICMP ping や異常な TCP トラフィックパターンを検知・警告する方法を習得します。この実験を終える頃には、独自の Snort ルールを構築、テスト、検証する方法が理解できているはずです。

ルールの構文とヘッダーの理解

このステップでは、Snort ルールの基本的な構造を学び、カスタムルールを保存するためのファイルを作成します。

ヘッダーは、実質的にスコープ(範囲)の定義です。どのトラフィックを評価する価値があるかを決定します。効率的な検知は、より詳細なコンテンツチェックを行う前に、候補となるトラフィックセットを可能な限り絞り込むことから始まるため、これは非常に重要です。広範なヘッダーは書きやすい反面、ノイズを増やす原因にもなります。

Snort ルールは、大きく分けて「ルールヘッダー」と「ルールオプション」の 2 つの論理セクションで構成されています。

ルールヘッダーには、ルールのアクション、プロトコル、送信元および宛先の IP アドレス、送信元および宛先のポートが含まれます。これは、「誰が」「誰と」通信しており、「どの」プロトコルを使用しているかを決定します。基本的な構文は以下の通りです。

[Action] [Protocol] [Source IP] [Source Port] -> [Destination IP] [Destination Port] (Options)

ヘッダーコンポーネントの内訳は以下の通りです。

  • Action: ルールの条件に一致するパケットが見つかったときに Snort が実行する動作(例:alert, log, drop)。
  • Protocol: トラフィックのプロトコル(例:tcp, udp, icmp, ip)。
  • IP Addresses: 送信元および宛先の IP アドレス。any を使用すると、すべての IP アドレスに一致します。
  • Ports: 送信元および宛先のネットワークポート。any を使用すると、すべてのポートに一致します。
  • Direction Operator: -> 記号はトラフィックの方向(送信元から宛先へ)を示します。双方向トラフィックには <> を使用することもできます。

独自のルールを作成するために、専用のファイルが必要です。デフォルトの作業ディレクトリ(~/project)にいることを確認し、local.rules という名前の新しいファイルを作成します。

touch コマンドを使用して空のファイルを作成します。

touch ~/project/local.rules

ディレクトリの内容をリスト表示して、ファイルが正常に作成されたことを確認します。

ls -l ~/project/local.rules

以下のような出力が表示され、ファイルが存在し、現在空であることが確認できるはずです。

-rw-r--r-- 1 labex labex 0 Jul 25 10:00 /home/labex/project/local.rules

ICMP 検知ルールの作成

このステップでは、ICMP トラフィックを検知するための最初の Snort ルールを作成します。ICMP(Internet Control Message Protocol)は、ping のようなネットワークユーティリティで接続確認によく使用されます。

ICMP はシンプルで認識しやすいため、学習に適した例ですが、同時に現実的な運用上のポイントも示しています。つまり、検知されたからといって必ずしも攻撃とは限らないということです。多くのネットワークでは、ping が正当に使用されています。アナリストの仕事は、ルールが一致した内容と環境的なコンテキストを組み合わせて、そのイベントが良性か疑わしいかを判断することです。

ここでは、あらゆる送信元からあらゆる宛先へ ICMP パケットが送信されるたびにアラートをトリガーするルールを作成します。

nano テキストエディタを使用して local.rules ファイルを開きます。

nano ~/project/local.rules

エディタに以下のルールを入力します。

alert icmp any any -> any any (msg:"ICMP Ping Detected"; sid:1000001; rev:1;)

このルールの意味を分解してみましょう。

  • alert: 実行するアクション。Snort はアラートを生成します。
  • icmp: 監視対象のプロトコル。
  • any any -> any any: トラフィックは任意の IP、任意のポートから発生し、任意の IP、任意のポートへ向かうことができます。
  • (msg:"ICMP Ping Detected"; sid:1000001; rev:1;): これらはルールオプションです。msg はアラートメッセージ、sid は一意の Snort ID(カスタムルールは 1,000,000 以上の ID である必要があります)、rev はルールのリビジョン番号です。

ルールを入力したら、Ctrl+O、Enter でファイル名を確定し、Ctrl+X で nano を終了して保存します。

次に、Snort がルールファイルを正しく認識できるかテストします。Snort には、検知エンジンを実際に起動することなく、設定やルールの構文エラーをチェックするテストモード(-T)があります。

以下のコマンドを実行してルールファイルをテストします。

sudo snort -T -c ~/project/local.rules

Snort が初期化される際に多くの出力が表示されます。出力の最後の方で、Snort が設定を正常に検証したことを示す成功メッセージを探してください。

Snort successfully validated the configuration!
Snort exiting

このメッセージが表示されれば、ICMP ルールは構文的に正しいということです。

TCP ポートアラートルールの作成

このステップでは、特定の TCP トラフィックを検知するルールを作成します。ICMP はポートを使用しませんが、TCP や UDP はポートを使用します。これにより、HTTP(ポート 80)や SSH(ポート 22)などの特定のサービスをターゲットにしたルールを作成できます。

ポートは、アプリケーションのコンテキストを大まかに把握する手がかりになります。すべてを物語るわけではありませんが、防御者がサービスの種類を区別するために最初に行う近似的な判断としてよく使われます。宛先ポート 80 をキーにするルールは、本質的に「Web サービスに向けられた可能性が高いトラフィックに関心がある」と言っているのと同じです。

ここでは、誰かがポート 80 の Web サーバーに接続しようとするたびにアラートを出すルールを作成します。

nano を使用して再度 local.rules ファイルを開きます。

nano ~/project/local.rules

既存の ICMP ルールの下に新しい行を追加し、以下の TCP ルールを入力します。

alert tcp any any -> any 80 (msg:"HTTP Traffic to Port 80 Detected"; sid:1000002; rev:1;)

この新しいルールのヘッダーを分析します。

  • alert tcp: TCP プロトコルに対してアラートを生成します。
  • any any: 送信元は任意の IP アドレス、任意のポートです。
  • ->: トラフィックは宛先に向かって流れています。
  • any 80: 宛先は任意の IP アドレスですが、宛先ポートは「80」である必要があります。

sid を 1000002 にインクリメントしたことに注目してください。すべての Snort ルールは一意の Snort ID を持つ必要があります。

ファイルを保存(Ctrl+O、Enter)し、nano を終了(Ctrl+X)します。

念のため、再度ルール構文をテストしてタイプミスがないか確認することをお勧めします。Snort のテストコマンドを実行してください。

sudo snort -T -c ~/project/local.rules

出力の最後までスクロールし、Snort が設定を正常に検証したことを確認します。これで 2 つのルールが正常に読み込まれたはずです。

ルールオプション(Msg, SID, Rev)の活用

このステップでは、「ルールオプション」セクションをさらに深く掘り下げます。オプションセクションは括弧 () で囲まれ、セミコロン ; で区切られたキーワードと値のペアが含まれます。

ルールオプションは、大まかなトラフィック分類を意味のあるアラートに変える場所です。明確な msg は、人間がイベントを理解する助けになります。一意の sid は、システムがどのルールが発火したかを追跡できるようにします。rev 値は、チームが時間の経過とともに検知内容を管理できるようにします。これらのフィールドは単なる構文ではなく、運用をサポートするものです。

すでに最も基本的な 3 つのオプションを使用しました。1 つ目は msg で、アラートログに出力されるメッセージであり、記述的であるべきです。2 つ目は sid(Snort ID)で、ユーザーが作成するルールは 1,000,000 より大きい SID を持つ必要があります。3 つ目は rev(リビジョン番号)で、ルールを修正するたびにこの数値をインクリメントしてバージョンの追跡を行うべきです。

これらのオプションの練習として、SSH 接続試行(ポート 22)を検知するルールを作成してみましょう。

local.rules ファイルを開きます。

nano ~/project/local.rules

ファイルの最後に以下のルールを追加します。

alert tcp any any -> any 22 (msg:"SSH Connection Attempt"; sid:1000003; rev:1;)

このルールでは、基本的な msg を設定し、新しい一意の SID(1000003)を割り当てました。

後でこのルールのメッセージをより具体的に更新することにしたと仮定します。その場合、msg を変更し、rev を 2 にインクリメントします。今すぐそれを行いましょう。ファイルの最後にある SSH ルールを以下のように修正してください。

alert tcp any any -> any 22 (msg:"Possible SSH Brute Force Attempt"; sid:1000003; rev:2;)

ファイルを保存(Ctrl+O、Enter)し、nano を終了(Ctrl+X)します。

最後に、3 つのルールすべてが完璧にフォーマットされていることを確認するため、もう一度構文チェックを実行します。

sudo snort -T -c ~/project/local.rules

検証成功のメッセージを探してください。これで、ヘッダーとオプションを使用して、複数のカスタム Snort ルールを正常に作成・構造化できました。

まとめ

この実験では、カスタム Snort ルールを作成するために必要な基礎スキルを学びました。ルールの構造を「ルールヘッダー」と「ルールオプション」に分けて探求しました。一般的な ICMP トラフィックや特定の TCP ポートトラフィックを検知するルールを正常に作成しました。さらに、msg、sid、rev といった重要なルールオプションを活用して、アラートを記述的かつ一意に識別可能にする方法を学びました。これらのスキルは、高度なネットワーク侵入検知シグネチャを作成するための基礎となります。