脅威ハンティングで正規表現を使用する(正規表現は意味不明な呪文ではありません!)
Security Tamara Chacon
とはいえ、正規表現を難しく感じる方もいらっしゃるでしょう。そのような方に役立つリソースが数多く提供されています。
- https://regex101.com:正規表現をテストできる人気のWebサイトです。自分が書いた正規表現が正しいかどうかをすばやく簡単にチェックできます。
- https://www.regular-expressions.info/:正規表現の初心者がその使い方を学べるWebサイトです。わからないことがあるときの参照先としても便利です。
ここで「でも、Splunkにはフィールドがあるのに、どうしてわざわざ時間をかけて正規表現を勉強しなければいけないのか?」と思う方もいらっしゃるでしょう。
たしかにそのとおりです。Splunkではすべてのログがインデックス化され、完全な形で保存されます(ここだけの話、特定のフィールドのみを保存する一部の あまり優秀とは言えない データプラットフォームとは違います)。さらに、どのデータソースでも主要なフィールドをサーチできます。ただし、場合によっては、アナリストとして脅威ハンティングで使いたい貴重な情報がデフォルトでフィールドに割り当てられないこともあります。
というわけで、脅威ハンティングで正規表現を使う方法をいくつかご紹介します。
(この記事は「Splunkで脅威ハンティング」シリーズの一部で、初稿はSteve Brantによって書かれました。お客様に最大限の価値を提供できるよう、その内容を最近更新しました。)
Splunkで正規表現を使用するための2つのコマンド
SplunkのSPLには、rexとregexの2つのコマンドがあります。アナリストは、これらのコマンドで正規表現を使って、サーチの中で値を新しいフィールドに割り当てたり、結果を絞り込んだりできます。各コマンドの使い方を詳しく見ていきましょう。
rexコマンド
rex [field=<field>] (<regex-expression> [max_match=<int>] [offset_field=<string>]) | (mode=sed <sed-expression>)
rexコマンドでは、フィールド内の文字を置き換えたり(データの匿名化に便利)、値を抽出して新しいフィールドに割り当てたりできます。脅威ハンティングでよく使うのは、値の抽出です。
例として、暗号化されていないパスワードが外部ネットワークに流出していることが確認され、その情報を特定し、分析のために抽出するとしましょう。まず、ネットワークデータでhttpトラフィックを調べたところ、Webログデータに「form_data」というフィールドが見つかりました。
その1件のイベントに、暗号化されていないパスワードが含まれています。Webログにはあってはならない状態です!
この暗号化されていないパスワードの流出がどのくらい広がっているかを調査するために、rexコマンドを使ってサーチを実行します。その中で「pass」というフィールドを作成し、その値を調べて、暗号化されていないパスワードを探します。サーチは次のようになります。
「form_data」フィールドに対してrexコマンドを実行し、「pass」という名前の新しいフィールドを作成しています。その中で呪文のような部分が、「form_data」からデータを抽出する正規表現です。すごいでしょう?結果を見ると、なんと「pass」という新しいフィールドが作成されています!
この新しいフィールドに対して、stats、eventstats、streamstatsなどの操作を実行できます。これらのコマンドの使い方については、John Stonerのブログ記事をご覧ください。
さて、先ほどのコマンドで一体何が起きたのでしょうか?新しいフィールドはどこから現れたのでしょうか?詳しく見ていきましょう。
下のコードは「form_data」フィールドの値です。注目していただきたい部分にマークを付けています。
username=admin&task=login&return=aW5kZXgucGhw&option=com_login&passwd=rock&4a40c518220c1993f0e02dc4712c5794=1
文字列「passwd=」はリテラル文字列で、毎回完全一致で検出するパターンです。この後に続く値が、分析のために抽出するパスワード値です。
パスワードを抽出するための正規表現は次のようになります。
passwd=(?<pass>[^&]+)
- 「?<pass>」では、抽出した値を割り当てるフィールドの名前を指定しています。この場合は「pass」がフィールド名です。正規表現の中のこの部分は、アンパサンド以外のすべての文字に一致します。
- 「[^&]+」の角かっこは1つのクラスを示し、かっこ内のいずれかの文字に一致します。キャレット記号は否定を意味します(クラス内で使用する場合)。つまり、この部分はアンパサンド以外の1文字に一致します。
- プラス記号は、直前の文字の1回以上の繰り返しを示します。「form_data」でアンパサンド以降は別の値を示すと考えられるため、このように指定することで、アンパサンドが見つかった時点で抽出を終了します。
- 丸かっこ「()」は、抽出するグループを示します。丸かっこ内で見つかった値が、指定した名前のフィールドに割り当てられます。
便利ですね!では次に、regexを見ていきましょう。
regexコマンド
regexコマンドでは、正規表現を使ってイベントをフィルタリングできます。
regex (<field>=<regex-expression> | <field>!=<regex-expression> | <regex-expression>)
このコマンドを実行すると、指定したパターンに一致する値が返されます。逆に、正規表現に否定を付けて、指定したパターンに一致しない値を取得することもできます。rexコマンドとは異なり、regexコマンドでは新しいフィールドは作成されません。
例として、Suricataのログでハンティングの対象を特定のネットワーク範囲(192.168.224.0~192.168.225.255)に絞り込むとします。evalコマンドでcidrmatch関数を使うこともできますが、regexをマスターすれば、ほかにもさまざまな場面で活用できます。
サーチは次のようになります。
regexコマンドを使わない場合、このデータセットのサーチ結果には、8.8.8.8や192.168.229.225のような、ハンティング対象でない値も含まれます。regexを使えば、目的のIP範囲内の値だけを取得できます。
サーチの内容を詳しく見ていきましょう。
src_ipフィールドには以下のような値が含まれています。
- 192.168.225.60 - 一致し、結果に表示される
- 192.168.229.237 - 一致せず、結果に表示されない
- 192.168.224.3 - 一致し、結果に表示される
次の部分が正規表現です。
192\.168\.(224|225)\.\d{1,3}
- 黄色で示した値、192と168は、一致する必要のあるリテラル文字列です。
- ピリオド「.」は正規表現で予約済みの文字なので、「.」を一致させるには、パターン定義で「.」の前にエスケープ文字のバックスラッシュを入れます。
- 3番目のオクテットは224または225で、これは正規表現の「|」を使って指定できます。この「または」のパターン全体を丸かっこ「()」で囲みます。選択肢が3つ以上ある場合は、「(224|225|230)」のように「|」を追加して値を指定します。
- 「\d」は1つの数字(0~9)を表します。先ほどのrexコマンドの例では「+」を使って直前の文字の1回以上の繰り返しを表しましたが、ここでは一致する文字数を限定します。「{1,3}」で直前の「\d」を1~3回繰り返すように指定することで、1~3桁の数字を表現しています。
正規表現は意味不明な呪文ではない
正規表現は意味不明な呪文なのでしょうか。そんなことはありません。とはいえ、拒否反応を示す人もいるでしょう。勇気を出して正規表現を身に付け、ハンティングでログを調査する際にパターンの検索に活用してください。
Splunkはセキュリティチームをいつでも支援いたします。
関連記事

求められるのは防御だけでなく“回復力” ― 今、実践すべきサイバーレジリエンスとは

セキュリティアナリストの役割:スキル、責任、および給与
