情報セキュリティ実務家のためのPowerShell超特急
まったくRの話題ではないのですが、他に適当な場所もないので、「情報セキュリティ実務家のためのPowerShell超特急」の講演資料へのリンクを置いておきます。ちなみに「超特急」というタイトルは、山本矩一郎さんの「数学超特急」という学習参考書から拝借しました。
SANS Community Night(2023-12-06)講演資料
MD5ハッシュ値: 2E32876EF80D4894169A4074138CE8A8
OWASP Sendaiでの内容からJSONに関する記述を増やし、参考文献を入れ替えました。
TMCIT × 大和セキュリティ(2023-03-26)講演資料
MD5ハッシュ値: 389EB388297743344E95CDF80F64DD53
PowerShellでJSONLを扱う方法を取り上げました。JSONLで与えられたWindowsイベントログ(sysmonを含む)を分析するCTFだったためです。
OWASP Sendai(2023-03-15)講演資料
MD5ハッシュ値: 1F8F3854C4AE20935CE4C352B534C9D2
持ち時間が30分増えたので、内容を増やしました。パス操作(*-Path)、ファイル入出力(ConvertFrom-Csv、Out-File)、作業証跡(*-Transcript)の話題を新規に取り上げたほか、パイプラインやイベントログの解説を強化しています。
SANS Community Night(2022-12-01)講演資料
MD5ハッシュ値: 25048554FC0EBDFEEED13383B9BF9E25
以下のリンクから講演の動画がご覧になれます(要アカウント登録)。 www.sans.org
contains演算子の構文糖をつくる
今回は思い付きの小ネタです。Rのstringrパッケージは一貫性が売りですが、やや冗長なところがあります。たとえば我々が行(ログの場合にはイベント)を絞り込むとき、大文字・小文字を区別せずにマッチさせたいことが多々あります。これをstringrで表現すると、次の通りです。
log_http |> filter(str_detect(uri, fixed("union", ignore_case = TRUE)))
フィルターが1行だけならともかく、現場ではフィルターを重ねることが少なくないので、str_detect()が重たく感じます。もっと気軽にKQLのcontains的に使いたくて、containsに相当する演算子を作ってみました。
"%~%" <- function(string, pattern) { stringi::stri_detect_fixed(string, pattern, case_insensitive = TRUE) }
こうすると、先ほどのフィルターは
log_http |> filter(uri %~% "union")
と書けます。含まない場合には、
log_http |> filter(!uri %~% "union")
でOK。スマホの画面にも収まる短さです。個人的に、めちゃくちゃ便利になりました。
Shift_JISのURLをデコードする
ログ分析の過程で、URLエンコーディングされたURLをデコードしたいことがあります。ところがurl_decode()関数はUTF-8にしか対応していないため、ファイル名などでShift_JISが登場したときに困ります。
そこで、下のような書き捨ての関数を作りつつ、stringrパッケージや関数のベクトル対応の要点を確認します。特に、str_replace()関数の置換文字列として関数が使用可能な点は、非常に使いでがあります。
url_decode_sjis <- function(urls){ url_decode_unit <- function(url){ url |> str_extract_all("(%.{2}|.)") |> flatten_chr() |> str_remove_all(fixed("%")) |> str_replace_all("^(.)$", function(x) as.hexmode(utf8ToInt(x))) |> as.hexmode() |> as.raw() |> rawToChar() |> stringi::stri_encode(from = "cp932", to = "utf8") } map_chr(urls, url_decode_unit) }
イベントの発生を視覚化する
今回は、横軸に時刻を、縦軸にアセットをとって、イベントの発生をプロットする手法を取り上げました。最終的に下のようなグラフをつくります。こうしたプロットを一貫した文法で記述できるのがggplot2のよいところです。
Linuxの認証ログをパースする
今回はsyslogのパースを取り上げました。syslogは典型的な半構造データで、意外と厄介な形式です。
正面から取り組む方法として正規表現を使う方法、裏口から取り組む方法としてElastic Stackにパースさせる方法を取り上げています。前者ではR 4.0から利用可能になったraw string形式を活用するのがポイント。後者では、前回少しだけ取り上げたhoist()関数を利用します。
スクリプトに認証情報を埋め込まないようにする
データレイクや各種情報サービスなどからWeb APIを使ってデータを取得することは珍しくありません。たとえばSplunkからデータを取得する方法としては、同社のブログ「Leveraging External Data Science Stacks with Splunk Today」(2019-03-18)が参考になります。
ただ、リンク先の例のような、パスワードをコードの中に平文で書き込む方法は安全ではありません。では、どうするか? 古典的には、環境変数に書いたり暗号化して別ファイルに保存することが行われます。しかしクライアント端末で実行する際には、OSが備えている鍵管理システムを利用するのが便利です。Windowsでは資格情報マネージャー(Credential Manager)が相当します。
資格情報マネージャーはどこにあるか?
資格情報マネージャーは、〈コントロールパネル/ユーザーアカウント/資格情報マネージャー〉にあります。Windows+R(ファイル名を指定して実行)でcontrol /name Microsoft.CredentialManager
と入力しても構いません。左側の「Web 資格情報」は、Internet Explorerが使用するもののようです。私たちがスクリプトで使うのは、右の「Windows 資格情報」です。
以下に、Rで資格情報マネージャーを取り扱う方法を示します。登録は永続化されますから、いちど登録すれば二度と登録する必要はありません。
keyringパッケージを使う
Rのkeyringパッケージは、資格情報マネージャーだけでなく、Keychain(macOS)やSecret Service API(Linux)にも対応しています。GitHubのページから付け加えることはないのですが、いちおう先のSplunkでの具体例を挙げておきます。
keyringパッケージをインストールする
KeyringはCRANに登録されているので、
install.packages("keyring")
でインストール可能です。
パスワードを登録する
keyring::key_set_with_value("splunk", username = "test@example.jp", password = "testpassword")
登録すると、資格情報マネージャーの「汎用資格情報」欄に追加されます。
登録一覧を眺める
keyring::key_list() service username 1 splunk test@example.jp
登録されたパスワードを取り出す
pwd <- keyring::key_get("splunk", "test@exapmle.jp")
(代入するとRStudioから丸見えになるので注意。)
登録されたパスワードを削除する
keyring::key_delete("splunk", "test@example.jp")
おまけ
Pythonの場合
keyringはPythonにもあります。私はふだんanacondaを使っているのですが、この環境では最初から入っていました。使い方はまったく同じです。
import keyring keyring.set_password("splunk", "test@exapmle.jp", "testpassword") pwd = keyring.get_password("splunk", "test@example.jp")
ならば形式も同じで両言語のkeyringが共用できるかというと、残念ながらうまくいきませんでした。RはUTF-8で、PythonはUTF-16で登録されるようです。
Splunk Authentication Token
Splunk 7.3からは、パスワードを使った認証ではなくAuthentication Tokenを使うことができます。ただし設定で有効化する必要があるので、Splunkの管理者に相談するのがよいでしょう。