
はじめに
こんにちは、情報セキュリティ部の兵藤です。日々ZOZOの安全を守るためSOC業務に取り組んでいます。
本記事ではサイバー脅威インテリジェンスプラットフォーム「OpenCTI」からSplunkへの脅威インテリジェンスの取り込みについて紹介します。また、この内容については以下の「OpenCTIをSentinelに食わせてみた」に関連した内容となっています。
目次
背景と概要
ZOZOのSOC業務において以前はMicrosoft Sentinelを活用していました。現在では業務範囲の拡大や運用効率化など、様々な理由からSplunk Enterprise Security(以降 Splunk ES)へ移行しました。移行に伴い、Sentinelで構築していた脅威インテリジェンスを用いた検知をSplunkでも行うため、OpenCTIからの脅威インテリジェンスの取り込み方法を再検討する必要がありました。
以前の記事では、Logic Appsを使用してOpenCTIからSentinelへ脅威インテリジェンスを取り込む方法を紹介しましたが、今回はSplunkに対応するため異なるアプローチを採用しました。
Splunkにはデータを取り込むための各種Add-onが提供されており、その中には「OpenCTI Add-on for Splunk」も含まれています。このAdd-onを利用することで、OpenCTIからSplunkへのデータ取り込みが容易になります。
上記を用いて、脅威インテリジェンスを用いた検知を自動で行うようにOpenCTIのインテリジェンスをSplunk ESに食わせました。
構築
以下の環境で構築しました。
- OpenCTI 6.9.13
- Splunk Cloud 9.3
- Splunk Enterprise Security 8.3
- ※ 最近バージョン7系から8系にアップグレードしました
Splunkへのログ移行
SentinelからSplunkへの移行に伴い、各種ログソースのデータをSplunkに取り込む必要がありました。Splunkはオンプレからクラウド環境まで各種ログをindexerというコンポーネントに取り込むことが可能です。取り込み方も多種多様で、各ログソースに応じた方法があります。ここでは、脅威検知の対象となるログの1つとしてMicrosoft Defender for Endpoint(MDE)を例に取り込み方法を紹介します。
Splunk Add-on
Splunkで脅威情報を検知するためには、MDEのインシデントやアラートのログだけではなくテレメトリのログを投入する必要があります。MDEのテレメトリログをSplunkに取り込むためには、「Splunk Add-on for Microsoft Cloud Services」を使用します。
また、ログを正規化(CIM化)するために「Microsoft Defender Advanced Hunting Add-on for Splunk」のAdd-onも追加します。
Microsoft Cloud ServicesのAdd-onを用いてMDEのログを取得するためにはAzureのアプリケーション登録が必要です。Splunkからこのアプリケーション経由でログをとりに行くのですが、そのためにはクライアントシークレットが必要なので以下の画像のようにそちらも登録します。
このシークレットを使用してAdd-onの設定上にある「Azure App Account」に登録します。
その後、Add-onの「入力」設定からどのようなログを取り込むかの設定をします。今回はAzureのEvent Hubs経由でMDEのログを取得するように設定しました。ここからの設定は事前にEvent Hubsを構築しておく必要があります。
ここでIndexやソースタイプなどを選択可能です。ソースタイプには「Microsoft Defender Advanced Hunting Add-on for Splunk」を入れたら適用できるようになるmscs:azure:eventhub:defender:advancedhuntingを設定するとCIM化ができます。
詳しくはこちらの公式ドキュメントを参照してください。
EventhubとMDEの設定
SplunkにMDEのログを取り込む為にEvent Hubsを作成する必要があります。詳しい作成方法は公式ドキュメントを参照してください。
先ほどSplunk Add-onで登録したAzureアプリケーションに、このEvent Hubsへの読み取り権限を付与することで、ログを読み取れるようになります。具体的にはAzureのARM APIを用いたロールです。Entraなどの設定ではなくAzure Resourceごとの設定となります。Event Hubsなどの「アクセス制御 (IAM)」の項目から設定できます。
ロールとしてはデフォルトで存在するものでは「Azure Event Hubs のデータ受信者」のロールを付与すればSplunkからログを読み取れるようになります。以前はSASを用いてアクセスする方法もありましたが、ロールを定義してアクセスする方法が推奨されています。
続いて、MDEからEvent Hubsへログを送信する設定します。MDEのポータルから「システム」→「設定」→「Microsoft Defender XDR」→「ストリーミング API」へ進み、「追加」をクリックします。以下のようにEvent Hubsの情報を入力できます。
これでMDEのログがEvent Hubsへ送信され、Splunk Add-onで取り込めるようになります。
SplunkでのOpenCTI連携設定
OpenCTI Add-on for Splunkの利用
OpenCTIからSplunkへ脅威インテリジェンスを取り込むには、Notionの「OpenCTI Ecosystem」に紹介されている以下の「Splunk App」を利用します。
SplunkbaseにはOpenCTI Add-on for Splunkで紹介されています。このAdd-onをSplunkにインストールし、OpenCTIとの連携設定を行います。基本的に、OpenCTIへのURLとAPIトークンを設定し、入力を作成するだけでOpenCTIからデータを取得できます。
入力欄の「Stream ID」はOpenCTI側で設定が必要です。Streamを作成しておきましょう。
OpenCTI側のStream設定
Streamの設定はOpenCTIの「データ共有」の項目から設定します。
「ライブストリーム作成」をクリックすると以下のようにStreamの作成画面が表示されます。
基本的に、APIトークンでアクセスするため、公開ストリームにする必要はありません。自作したGroupを「アクセス可能」の欄に設定するだけでそのGroup内に所属するUserであればこのStreamにアクセス可能となります。例えば、SOC運用でOpenCTIを利用しているGroupを作成し、そのGroupにアクセス権限を付与すると以下のようになります。
これでSOC運用を行なっているメンバーがこのStreamへアクセスできるようになります。うまくStreamできていることが確認できれば、Stream読み取り用のロールを持つGroupを作成しておくと良いでしょう。
また、Splunkに連携するインジケータもフィルタリングして選別が可能です。以下のようにスコアなどでフィルタリングできます。
条件をつけ作成したら以下のようにStream IDの発行されたライブストリームが作成されます。例としてAbuse.chのフィードを流すStreamを作成しました。
最後に開始ボタンを押してStreamを開始します。
その後、このStream IDをSplunkのAdd-on側で設定すればOpenCTIからSplunkへデータが流れ込みます。以下のようにAdd-onの「Indicators Dashboard」で確認できれば接続成功です。
運用
ここからの運用のお話はSplunk ESのバージョン7系のものを引き継いだ内容を記載します。8系の最新機能などはあまり含まれていないため、ご了承ください。
Splunk ESでのThreat Intelligence framework
Splunk ESで脅威インテリジェンスを活用するにはどのようなフレームワークを用いているか理解するとスムーズです。どのようなイメージでインテリジェンスを処理しているかはSplunk DEVのドキュメント1の図を見るとわかりやすいです。
簡単に整理すると、インテリジェンスのデータソースから読み込んだ脅威インテリジェンスを正規化し、Splunk内にkvstore(脅威インテリジェンスのマスタテーブルに相当するもの)として保存されます。その後、Threat_Intelligenceのデータモデルがある程度マッチさせてくれます。
Splunk ESでの具体的な名称は以下のようになります。IPアドレスの場合を例に挙げます。
- データソース:
local_ip_intelemerging_threats_compromised_ip_blocklist
- kvstore:
ip_intel
OpenCTIのインジケータをThreat Intelligence frameworkに組み込む
ではここでOpenCTIのインジケータがAdd-onを通じてSplunkにどのように取り込まれているか確認します。Add-onの解説を見ると、以下のようにopencti_lookupのkvstoreに保存されます。
Add-onにはこのkvstoreを用いたカスタムアラートアクション作成手順が記載されています。ですが、ここではSplunk ESのThreat Intelligenceのframeworkに組み込む方法を紹介します。
Splunk ESのインテリジェンスのデータソースの設定は「設定」→「Threat intelligence」→「Threat intelligence sources」から確認できます。ローカルからのソース設定もできますが、kvstoreの設定はないので直接opencti_lookupから取り込むことはできそうにありません。そのためopencti_lookupの内容を既存のlocal_ip_intelやlocal_file_intelなどのデータソースに流し込む必要があります。
解決策としてスケジュールサーチを用いてopencti_lookupからデータを正規化し、各データソースに流し込む方法を採用しました。データソースに流し込むためのフィールドは公式ドキュメントを参考に設定できます。
以下はIPアドレスのSPL例です。
| inputlookup opencti_lookup
| where type IN ("ipv4-addr", "ipv6-addr") AND strptime(valid_from, "%Y-%m-%dT%H:%M:%S.%QZ") <= (now() - 9*3600) AND relative_time(now(), "+12h") <= strptime(valid_until, "%Y-%m-%dT%H:%M:%S.%QZ")
| eval description=created_by, ip=value, weight=score
| fields description ip weight
| outputlookup local_ip_intel
インジケータの有効期限のフィールドvalid_fromやvalid_untilもOpenCTI側で設定できるため、これらを用いて有効なインジケータのみを取り込むようにしています。また各種フィールド名もSplunk ESのデータソースに合わせて変換しています。最後にoutputlookupでデータソースに流し込みます。descriptionのフィールドは脅威検知のSPLで見ることができる項目のため、こちらに好きなフィールドを設定すると良いでしょう。例えばcreated_byに設定しておくとどこからのインテリジェンスなのかが一目でわかります。またこの設定だと同じインテリジェンスが複数回local_ip_intelに流し込まれます。ですがthreat_keyをKeyとしたkvstore内では上書きが走るだけなのでkvstore内のデータが膨れ上がることはありません。既存のインテリジェンスがあるものはjoinを利用しwhereで除外する方法もありますが、最新の情報に更新したい場合はkvstoreの性質を活用し上書きする形が適していました。
このスケジュールスキャンをどのタイミングで実行するかはlocal_ip_intelがip_intelに取り込まれるタイミングによって設定すれば良いです。デフォルトの値は12時間(43200s)なので、12時間毎にとりあえず試してみるのも良いでしょう。この値は変更できるので好きなタイミングで実行間隔を制御できます。
Threat Activity Detected ルール
kvstoreに格納されたOpenCTIのインテリジェンスを用いて検知するルールは「Threat Activity Detected」のEvent-based detectionのみで完結します。Splunkのデータモデルが活きてくるいい例です。
このdetectionのSPL冒頭は以下となっており、単純にマッチしたThreat_Activityを拾ってくるだけで検知することがわかります。
| from datamodel:"Threat_Intelligence"."Threat_Activity"
どのようなログのデータをマッチさせているかは「Threat matching」の項目から確認できます。例えばsrcフィールドに入ってくるIPとマッチさせる設定は以下のようになっています。
各データモデル(All_TrafficやWebなど)のsrcに脅威インテリジェンスのIPアドレスがマッチした場合にThreat_Activityとして検知されます。OpenCTIから取り込んだインジケータもこのip_intelに格納されているため、OpenCTI由来のインジケータであっても問題なく検知されます。
逆に言えば、各種データモデルのtagが付いてない生ログだとこのデータモデルにログとして取り込まれないので検知がされません。MDEのCIM化されたログは基本的にnetworkなどはついているものの、webなどのtagがついていません。MDEのログと脅威インテリジェンスの以下urlなどの項目をマッチさせるためには別途「計算済みフィールド」と「タグ」の設定を追加する必要があります。基本的にMDEはエンドポイントのログなのでurlの設定はお好みで良いでしょう。今回はIPのマッチングやファイルハッシュのマッチングに絞って記載します。
「Threat Activity Detected」はデフォルトの状態からONにするだけで利用できます。ですが、公開サーバのログを取り込んでいる場合はsrcのマッチングで大量検知の可能性があります。destで抜けていく通信は見たいが、srcで来るものは除外する要件がある場合には工夫が必要です。そこで、ZOZOでは必要に応じてルールの条件を以下のように絞っています。
| where NOT (orig_sourcetype="<公開Productのトラフィックログソースタイプ>" AND source="threatmatch://src")
このようにすることで、公開サーバのトラフィックログでのsrcマッチングを除外しています。必要に応じて条件を追加してみてください。
実際に検知が起こると以下のように表示されます。
MDEのファイルハッシュのバージョン差分
MDEのログをCIM化する「Microsoft Defender Advanced Hunting Add-on for Splunk」のAdd-onアプリによって以下のfile_hashで検知挙動に大きく差が出ます。
このAdd-onのバージョン1.4.2より前ではMD5のハッシュ値がfile_hashフィールドに格納されていました。1.4.2以降のバージョンではSHA256のハッシュ値が格納されるようになりました。この変更後OpenCTIから取り込んだインジケータでSHA256のハッシュ値を用いている場合、file_hashでのマッチングが行われます。元々MD5でインジケータを取り込んでいる場合はマッチングされなくなるため注意が必要です。
この変更はCommit 0684d4d2で行われた内容のようで、最新のバージョン1.4.2でSplunkbaseに組み込まれたようです。GitHub上では、まだ1.3.9のリリースしか見えないため、バージョン管理が少しわかりづらいですが、Splunkbase上のバージョンを確認して適切なバージョンを利用してください。
除外の設定
脅威検知まではこれでできるようになりますが、このインテリジェンスは調査の結果「検知までする必要はないかも」といったケースも出てきます。そういった場合はサーチマクロを作成し、除外設定を行います。以下が一例です。
where NOT threat_match_value IN ("<IPアドレス1>", "<IPアドレス2>")
このマクロを「Threat Activity Detected」内のSPLに追記するだけで除外が可能です。
8系では、SafeListという除外リスト機能が追加されています。今後はこちらを活用していくことも検討しています。
まとめ
本記事ではOpenCTIからSplunkへ脅威インテリジェンスを取り込み、Splunk ESで脅威検知する手法について紹介しました。OpenCTI Add-on for Splunkを用いることで比較的容易に連携が可能となり、SOC業務での脅威インテリジェンス活用が促進されます。
OpenCTIを用いた自動でのインテリジェンス検知運用の記事は事例が少ないので、参考になれば幸いです。
ZOZOではこれからも脅威インテリジェンスを逐次収集し、SOCの検知能力の向上に努めていき、ZOZOの安全性を高めていきたいと考えています。
おわりに
ZOZOでは、一緒に安全なサービスを作り上げてくれる仲間を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください!