Splunk Search APIを使ってセキュリティ調査過程を残す
Security Guestこのゲストブログは、JCOM株式会社の情報セキュリティ本部・専任部長である渡辺慎太郎氏によって執筆されました。
WebコンソールだけがSplunkではない
DFIR (Digital Forensics and Incident Response)を生業としている身として、ログ分析にSplunkを使わない日はありません。フィールドを後付けで割り当てられるSchema on the Flyや、処理をパイプでつなげていけるSearch Processing Language (SPL)は、試行錯誤が必要なDFIR業務と相性がよいのです。
しかし、Splunkの機能はWebコンソールだけではありません。Search APIを使うことで、さらに可能性を広げることができます。たとえば後日の振り返りに備え、サーチ文やサーチ結果を残しておきたいと思ったことはありませんか?コメントをつけたいと思ったことはありませんか?
Search APIを使えば実現可能です。
百聞は一見に如かずで、Search APIを使ってBoss of the SOC v3データセットの調査過程を記録したHTMLファイルを用意しました。リンク先のファイルは実際にIDE (RStudio)でサーチ文を含むコードを書き、そのまま実行して結果を取得し、HTMLに変換し、サイトに載せたものです。
興味がわきましたか? これから、環境構築の要点を解説します。
MSTICPyでSearch APIをラップできる
APIの利用には認証やレートリミット、ページネーションなど考慮すべき点が多くあり、DFIR実務者が仕様を理解して実装するのは骨が折れます。その苦労を担ってくれるラッパーがMSTICPy (Microsoft Threat Intelligence Python Security Tools)です。MSTICPyは脅威ハンティングのためのPythonライブラリで、さまざまなデータソースからログを取得し、分析や可視化を支援します。SplunkやSplunk Cloudにも対応しています。
嬉しい点は、サーチ文を書いてSearch APIに投げると、結果をPandasデータフレームに変換して返してくれることです。おかげで、Splunkで行った分析を手元で続けることができます。
MSTICPyはPyPIに収録されていますから、pipコマンドでインストール可能です。ただし、後述のRStudioから使うときには、pandas 1.5系を指定する必要があります。上に紹介したページはWindows版のMiniforge環境において、以下のコマンドでmsticpyという仮想環境を作り、MSTICPyをインストールしました。
> conda create -n msticpy python=3.10 pandas=1.5.3 pip notebook ipykernel
> conda activate msticpy
> pip install msticpy[splunk]
Quarto/RStudioでMarkdownにサーチが埋め込める
上に紹介したページは、QuartoでHTML化されています。指定するコード実行エンジンに依存しますが、たとえばknitrを選択した場合には、地の文章をRMarkdown形式で記述しつつ、好きな場所にコードチャンクを埋め込めます。Jupyterのようなセルの概念はありません。
上の画面の通り、1つの文書の中にR、Python、Bashのコードを混在して記述でき、実行可能です。そしてコンパイルすると、コードと結果とが一体となったHTMLファイルが出力されます。
QuartoはVSCodeやvimなど任意のエディターで利用できますが、初めての方にはQuartoがバンドルされたIDEであるRStudio DesktopやRStudio Serverをお勧めします。以前はR用でしたが、現在はPythonにも対応しています。それどころか、Reticulateパッケージを用いると、RからPythonオブジェクトが透過的に扱えます。この記事で用いられているスクリーンショットは、RStudio Serverのものです。
サーチ結果をHTMLに表示するまで
Splunkに接続する
私はR使いなのでRのコードで紹介させてください。
まず、SplunkにAPI接続します。1~2行目はパッケージのインストールと呼び出しですから、気にしないでください。重要なのは3行目からで、msticpyオブジェクトを変数mpに代入し、QueryProviderにSplunkを指定して、connect()メソッドで接続しています。
install.packages("pacman") # もしpacmanパッケージが未インストールなら
pacman::p_load(tidyverse, reticulate)
mp <- import("msticpy")
qry_splunk <- mp$QueryProvider("Splunk")
qry_splunk$connect(host = "172.17.0.1", port = "8089",
username = "admin", password = "testpassword") # 危険
これは、Pythonで次のように書くことに相当します。
import msticpy as mp
qry_splunk = mp.QueryProvider("Splunk")
qry_splunk.connect(host="172.17.0.1", port="8089",
username="admin", password="testpassword") # 危険
今回はテスト接続のためパスワードをベタ打ちしていますが、これは悪い例です。本来はmsticpyconfig.yamlに記載すべきです。また、パスワードの代わりにAPIキーを使うこともでき、そちらを薦めます。
サーチ結果を取得する
次に、適当なサーチ文を書いて変数に代入します。r"(...)"はRにおけるraw文字列の記法です。
spl <- r"(
| inputlookup security_example_data.csv
| table timestamp threat_src_ip threat_dest_ip threat_status
| head 5
)"
サーチを実行するにはexec_query()メソッドを使います。結果を格納したsample_dfという変数に代入します。これはデータフレームなので、_dfという接尾辞を入れてあります。次に、sample_dfを表示させます。
sample_df <- qry_splunk$exec_query(spl)
sample_df
結果が得られました!
変数化したデータフレームは別タブや別ウィンドウとして、いつでも参照できます。
ただ、timestampフィールドがUnix timestampで、文字列型ですね。実は、API経由で取得したデータはすべて文字列型になってしまいます。
これは見づらいので、日時型に変換しましょう。これにはRのパイプラインを使います。私はTidyverseというデータ分析パッケージの一貫した操作性が大好きです。SPLのパイプにも似ていますよね。
sample_df |>
mutate(
timestamp = timestamp |> as.numeric() |> as_datetime()
)
これで、人間に読めるtimestampになりました。
HTMLファイルに変換する
ここまでRStudio IDEの画面上で編集してきました。入力した内容をHTMLファイルに変換しましょう。それには「Render」ボタンを押します(短縮キーはCtrl+Shift+K)。すると、背後でいろんな処理が走り、最終的には下のようなHTMLファイルが出力されます。
これで、サーチ文とサーチ結果と地の文とを一括して扱えるようになりました。
文芸的ログ分析へ
いかがでしたか? コードと結果と考えとを合わせて記載するこの手法を、私は文芸的ログ分析と呼んでいます。2018年に聞いた長久勝さんの「文芸的コンピューティング」という講演に感銘を受け、それをSplunkで実現したいとずっと思ってきました。ここ何年かで、MSTICPyとQuartoという2つのOSSツールが登場したおかげで、達成可能な目標となりました。
おもしろそうだと思ったら、ぜひ試してみてください。よきSplunk生活を! ついでにRにも触れてみてくださいね!
主たる保有資格にCISA、CISSP、GCIA、GDSA、GCIH、GPEN、GXPN、GWAPT、GCFA、GNFA、GCFR、GREM、ITストラテジスト、ITサービスマネージャ、システム監査技術者。『情報セキュリティ概論』(日本工業出版、2019年、共著)などの執筆のほか、各種講演の実施やSANS SEC504の授業を担当している。データを可視化するのが好き。
関連記事

2022年のIDC SIEM市場シェアレポートでSplunkが3年連続でSIEM部門のNo.1プロバイダーに選出

ゼロトラストとは?ゼロトラストセキュリティモデルとZTNAを解説
