さあ大変!ハッキングを受けてしまいました。社内のエキスパートに状況を調べてもらっています。ほどなくして、サイバーセキュリティ担当者からこう告げられます。「攻撃者がDNSを悪用して、感染したホストを操り、データを盗み出したようです」
後日振り返って、こう思うのではないでしょうか。「そもそも、こういう攻撃に対して勝ち目はあったのか?」
勝ち目はありました。Splunkを使えば、DNSを悪用したデータ窃取を検出し、対応できるのです。実は、DNSデータとSplunkを活用してネットワーク侵害の痕跡を見つけ出す方法は20年ほど前から使われています!
熱心な読者の皆様は「Splunkで脅威ハンティング:アクティブなハンターのためのハンズオンチュートリアル」をすでにお読みでしょう。それならば、良いハンティングは1~2個の仮説で始まることをご存知のはずです。さっそく仮説を立ててみましょう!この記事では、DNS悪用によるデータ窃取という積年の課題を取り上げ、その可視化、ハンティング、撃退方法について説明します。
(この記事は「Splunkで脅威ハンティング」シリーズの一部で、初稿はDerek Kingによって書かれました。お客様に最大限の価値を提供できるよう、その内容を最近更新しました。)
DNS悪用によるデータ窃取とは
この記事で取り上げる「DNS悪用によるデータ窃取」とは、攻撃者がDNSプロトコルを悪用して、標的組織から盗み出したデータを自身のホストにトンネリングする(抜き出す)攻撃を指します。DNSを使う目的について2つの仮説を立てることができます。
- 組織から外部に機密ファイルを転送する。
- 悪質なインフラと通信するためのサイドチャネルとして使用する。
適切な可視化とサーチ技法を使えば、正常時と比較して、または他のクライアントと比較して異常な動作をしているクライアントを見つけ出すことができます。
DNSデータの取得元
すでにDNSデータをSplunkに取り込んでいるならば準備完了です!まだ取り込んでおらず、私の同僚のRyan KovarとSteve Brantによる.confのプレゼンテーション「既知の未知を追跡する(DNS編)」(英語)をご覧になっていない場合は、ぜひ見てやってください。役に立つ情報が満載です。このプレゼンテーションがお気に召さなくても、この2人はあまり気にしないので大丈夫です。
いずれにしても、DNSデータのソースとしてお勧めするのは以下のログです。
- WindowsレガシーDNSデバッグログ
- DNS分析ログ
- Zeek DNSログ
- Splunkストリーム
これからご紹介するサーチをサンプルデータでお試しになりたい場合は、GitHubに用意されているBOTSv3データセットをご利用いただけます。ただし、以下のサーチはすべて、こちらから入手できるBOTSv1データセットを使ってテストされています。
DNS悪用によるデータ窃取の痕跡
DNS悪用によるデータ窃取の被害にあっているかどうかを調べるにはどうすればよいでしょうか?前述の仮説を裏付ける事象はたくさんあります。たとえば、ホストが侵害を受けている場合は、DNS通信に次のような変化が現れる可能性があります。
- クライアントからのリクエスト数の増加:C&C (コマンドアンドコントロール)通信やデータ転送が行われている可能性があります。
- 送受信するリソースレコードのタイプの変化:たとえば、通常はTXTレコードを送信しないホストからTXTレコードが送信される、などです。
- リクエストの長さの変化:DGA (ドメイン生成アルゴリズム)やエンコード/難読化されたデータストリームが使われている可能性があります。
- リクエスト間隔のばらつき:間隔が一定の場合はC&Cにビーコンを送信している可能性があります。
- ドメイン名のランダムな変化:DGAが使われている可能性があります。
- よく似ているが微妙に異なるドメイン名の使用:タイポスクワッティング(正規のドメイン名とよく似たドメイン名の悪用)が行われている可能性があります。
これらの攻撃手法は、stats、timechart、table、stdev、avg、streamstatsなどのコマンドを使ったSplunkサーチで検出できます(各コマンドの詳細については、それぞれのドキュメントを参照してください)。
DNSの脅威ハンティング
以下のセクションでは、上記の痕跡を調べてDNSの悪用を検出する方法をいくつかご紹介します。
注:いつものように、サーチは共通情報モデル(CIM)に準拠して記述されています。必要な場合は、環境に合わせてソースタイプ/タグ/イベントタイプを変更してください。
リクエスト数トップ10のクライアント
クライアントのリクエスト数の急増や変化は、データ窃取の初期兆候である可能性があります。
tag=dns message_type="Query" | timechart span=1h limit=10 usenull=f useother=f count AS Requests by src
まずは、時系列での変化を検出するために役立つシンプルなサーチをご紹介します。1行目で目的の結果セットを取得してから、2行目のtimechartコマンドで1時間ごとのリクエスト数をグラフ化します。
他のクライアントと比較してリクエスト数が異常に多いクライアントは、DNS通信によるデータ転送に悪用されている可能性があります。
リソースレコードごとのリクエスト数の変化
クライアントがリクエストするリソースタイプの変化は、C&C通信やデータ窃取が行われている可能性を示します。AレコードとTXTレコードを重点的に監視するのが一般的ですが、不意打ちで別のタイプのレコードが悪用される可能性も考慮しましょう。
tag=dns message_type="QUERY" | timechart span=1h count BY record_type
今回もシンプルに、先ほどと同じデータセットを使用し、timechartコマンドで、レコードタイプフィールド別に1時間ごとのリクエスト数をグラフ化します。前のサーチで検出したクライアントIPを対象としてこのサーチを実行すれば、仮説の検証にさらに役立つでしょう。
挙動の変化を早期に発見すれば、ホスト侵害の影響を軽減できる可能性が高まります。Splunkで過去のデータをサーチすることで、ホストが最初に侵害を受けた日時と、それ以降に通信した相手を特定することもできます。
パケットのサイズと数の分布
パケットサイズが著しく大きいリクエストや大量のリクエストが発生している場合は、データの窃取が疑われます。
tag=dns message_type="QUERY" | mvexpand query | eval queryLength=len(query) | stats count by queryLength, src | sort -queryLength, count | table src queryLength count | head 1000
コマンドが急に増えましたね!1つずつ見ていきましょう。どれもとても便利なコマンドです。
まずは、これまでと同じ基本サーチでBOTSv1データセットからデータを取得した後、以下の操作を行います。
- mvexpandコマンドを使って、複数値のフィールドを展開します。
- evalコマンドとlen関数を使って、queryフィールドの長さを調べます。
- statsコマンドを使って、リクエストの長さ(1行前のevalステートメントで調べたもの)とsrcフィールドごとに結果をカウントします。
- sortコマンドを使ってリクエストの長い順、数の多い順にソートしてから、tableコマンドを使って結果を表に出力し、headコマンドを使って上位1,000件のみを表示するようにフィルタリングします。
- その結果を散布図で表示します。
この散布図を見て、通常のパターンとは一致しないリクエストを特定できます。数が多いリクエストやパケットサイズが大きいリクエストは注意が必要です。
たとえば、通常は「www.bbc.co.uk」(13文字)や「www.facebook.com」(16文字)程度のリクエストがまばらに発生する中で、悪質なソフトウェアが5MBの機密文書を255バイトのパケットに分割してDNSリクエストとして送信しようとした場合、255バイトのパケットが大量に発生します。
ビーコンアクティビティ
次は少しレベルアップします。ここでは、C&Cインフラにビーコンを送信している可能性のあるクライアントを検出します。ビーコンアクティビティは、侵害されたホストがC&Cインフラに「照会」する際に発生します。こうしてビーコンを使って、次の指示や悪質なソフトウェアのアップデートを受け取る準備ができていることを知らせることがあります。
tag=dns message_type="QUERY" | fields _time, query | streamstats current=f last(_time) as last_time by query | eval gap=last_time - _time | stats count avg(gap) AS AverageBeaconTime var(gap) AS VarianceBeaconTime BY query | eval AverageBeaconTime=round(AverageBeaconTime,3), VarianceBeaconTime=round(VarianceBeaconTime,3) | sort -count | where VarianceBeaconTime < 60 AND count > 2 AND AverageBeaconTime>1.000 | table query VarianceBeaconTime count AverageBeaconTime
この例も基本はこれまでと同じですが、新しいコマンドがいくつか登場します。
- fieldsコマンドを使うと、処理を高速化できて便利です。後続のコマンドで必要なフィールドだけを残すことで、処理スピードが大幅に向上します。忍者のように疾風の如く仕事を終えることができますので、ぜひお試しください!
- streamstatsコマンドとevalコマンドでは、Splunkが直前に取得した2件のイベントの時間間隔(秒単位)を計算しています。streamstatsのこの使い方は実に見事です!(詳しくは、ブログ記事「ハンティングをするならstatで!」(英語)をご覧ください。)
- 次に、本題のビーコン検出に入ります。大人気のstatsコマンドを使って、クエリーの時間間隔の平均と分散を調べ、端数処理とソートを行います。
- 最後にwhereコマンドを使って、ノイズを取り除きます。
この例では、クエリー間隔の分散が小さいクライアントを特定しています。このようなクライアントがある場合、ホストが、30秒間隔や5分間隔など、一定の間隔でC&Cインフラと通信している可能性があります。
ビーコンドメインと通信しているホスト数
特定のドメインと通信しているホスト数を特定することは、ボットアクティビティが行われている可能性や、すでに侵害されているホストの範囲を調べるために役立ちます。
tag=dns message_type="QUERY" | fields _time, src, query | streamstats current=f last(_time) as last_time by query | eval gap=last_time - _time | stats count dc(src) AS NumHosts avg(gap) AS AverageBeaconTime var(gap) AS VarianceBeaconTime BY query | eval AverageBeaconTime=round(AverageBeaconTime,3), VarianceBeaconTime=round(VarianceBeaconTime,3) | sort –count | where VarianceBeaconTime < 60 AND AverageBeaconTime > 0
このサーチには新しいコマンドは出てきません。ビーコンアクティビティを検出し、その通信を行っている個々のホスト数を調べています。これにより、侵害されているホストが複数あってもすばやく見つけ出すことができます。このサーチでは、statsコマンドで新しい関数を1つ使用しています。
- dc (「distinct count」の略)では、同じアクティビティを行っているホストを1つのホストとして、ホスト数をカウントしています。
この例は、前のビーコンアクティビティの例と比べて、一定の間隔で発生するリクエストを調べる点は同じですが、同じ動作をしているクライアントを1つにまとめている点が異なります。
多数のサブドメインを持つドメイン
エンコードされた情報はサブドメイン経由で転送されることがあります。1つのドメインで使用される異なるサブドメインの数を調べれば、コマンドアンドコントロール通信やデータ窃取を特定するために役立ちます。
tag=dns message_type="QUERY" | eval list="mozilla" | `ut_parse_extended(query, list)` | stats dc(ut_subdomain) AS HostsPerDomain BY ut_domain | sort -HostsPerDomain
ここでは、各ドメインについてリクエストされるサブドメイン数を調べています。この動作は、データ窃取やDGAが行われている可能性を示します。 URL Toolboxを使えば、ドメイン名を簡単に解析できます。詳しくは、ブログ記事「UTでスリザリン生のように狡猾にドメインを解析する」(英語)をご覧ください。
いつもどおり、DNSデータセットから対象のデータを取り込み、「mozilla」の値を持つフィールドを作成します。上記の記事をお読みになった方は、ここで何を行っているかおわかりでしょう。お読みになっていない場合は、とにかくURL Toolboxで必要な操作だとお考えください。;-)
「ut_parse_extended」の後は、すでにご紹介したコマンドを使用しています。statsコマンドで、ドメインごとの個々のサブドメイン数をカウントしてから、結果を降順にソートしています。
ダッシュボード
この例では、サブドメイン数が多いドメインを調べています。その結果から、問題ないと考えられる一般的なサイトをフィルタリングして取り除くと、もっと効率的に調査できます。
Splunkではこの作業を「Get shi stuff done! (汚れ仕事を片付ける)」と言っています。ここでうれしいお知らせです。上記のサーチはすべて、こちらのGitHubリポジトリからダウンロードできます。ぜひハンティングにご活用ください。
結果の品質を向上させるためのヒント
サーチ結果の品質を向上させるためのヒントをいくつかご紹介します。
- lookupsを使い倒してノイズを徹底的に排除する。上記のサブドメインの例では、「chickenkiller.com」のような名前のドメインのサブドメイン数が多いことは、「microsoft.com」のサブドメイン数が多いことよりもずっと重大です。Ryanによるブログ記事「ハンティングに繰り出す前にlookupで下調べ」(英語)の優れたアドバイスに従って、ノイズを取り除きましょう。
- Splunkが提供する検出機能を活用してデータ窃取を探し出す。Splunk脅威調査チームが、データ窃取を探し出すために役立つ検出機能をいくつか作成しています。まずはブログ記事「データ窃取の検出」(英語)をご覧になることをお勧めします。
- 休業日は除外する。
- 余分なノイズを排除する。そのためには、whereコマンドを利用できます。
- ポストプロセスサーチの実行を検討する。時間を劇的に節約できます!
- 動的なダッシュボードで特定のクライアントを集中的に監視する。
Splunkはセキュリティチームをいつでも支援いたします。
追記:ランダムな変化について
この記事では、ドメイン名のランダムな変化の検出方法については説明を省きました。タイポスクワッティング(「typo squatting」の代わりに「typ0 5quatting」を使うなど)やその他の数学的なランダム性についてご興味がある場合は、以下の記事をご覧ください。
このブログはこちらの英語ブログの翻訳、阿部 浩人によるレビューです。