PhishTank調査を自動化したい - part2

今月の目標

前回に引き続いてですが

①フィッシングサイトのURLを取得
②フィッシングサイトへのアクセス
③フィッシングサイトへ認証情報(正規の認証情報ではない、IDと環境は自分持ち)を入力
④Azure ADへのサインイン試行の確認

のサイクルを出来る限り楽にしたい、というのが本稿の目的となります。
前回は①をLog Analyticsを使って実施しました。

今回は②~③を自動化しておきたいので以下のようなコンセプトで要件定義します。
・フィッシングサイトの生き死にが視覚的に確認できること
・PCを開かずにアクセスできること
・フィッシングサイトURLごとに入力する資格情報のエイリアスを変更できること

視覚的に生き死に確認ってどうしよう?

フィッシングサイトURLの一覧を順番にアクセスして生き死にを確認するのは時間がかかります。
一応PhishTankの結果にonlineというカラムがあるためこちらからも確認できますが、実態としてabuseされテイクダウンされているものも多数あります。

画像1

そのため実際のフィッシングサイトURLアクセス画面を取得する必要があります。
都度アクセスしてもいいのですが、面倒なので自動化して画面キャプチャだけ取得したいです。
今回は画面キャプチャ取得のためにurlscan.ioを使用します。

urlscan.ioの説明自体は割愛しますが、APIとしてSubmission APIが用意されています。
このAPIを使用してURLへの代理アクセスを行ってもらい、返り値のUUIDを

https://urlscan.io/screenshots/<UUID>.png

として付与してアクセスすることで代理アクセスの結果(=画面キャプチャ)を得ることができます。
PhishTank上のURLに対してSubmission APIを定期的に実行できるようにシステム設計をします。

話題のAzure Sentinelを使う

前回の記事でMicrosoftブランドのフィッシングを抽出できているので、その際に作成したLog Analyticsを元にAzure Sentinelを構成して分析ルールの設定を行います。

画像2

1日に1度の頻度でPhishTankの一覧確認を行い、得られたMicrosoftフィッシングサイトの結果が1件以上あればそのURLをエンティティとして定義してトリガーされます。
さらにこのルールに合致した場合、urlscanioプレイブックが自動的に実行されSubmission APIが動くように設定します。
※urlscanioプレイブックは事前に用意が必要です

画像3

プレイブックとはAzure Logic Appを指しています。Logic Appで自動実行させたい処理を定義していきます。

画像9

プレイブックではトリガーされたルールに定義されているエンティティの取得を行い、
取得したURLに対してsubmissionを行ったあとに元々のURLとそれをuslscan.ioに送信した返り値となるUUIDを保存するようにしています。
submissionを行うためにAzure Functionsを使用してPowershellでAPIリクエストを行っています。
(Azure Functionsを使わずとも実行できますが、Logic AppよりPowershellを直接編集するほうがデバッグしやすいのでAzure Functionsを利用)
※記事を書いていて気づきましたがSubmissionのステータスコードを取得してエラー処理入れたほうがいいですね ←趣味用に作るからと言い訳して全体的にエラー処理入れていない

Azure Functions内のコードは以下。
(ほとんどデフォルトなのはご愛嬌)
POSTメソッドでフィッシングサイトURLを受けてその後 "https://urlscan.io/api/v1/scan/" 宛に送信しています。

using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."

# Interact with query parameters or the body of the request.
$url = $Request.Body.Url
Write-Host $url

$body = "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."

if ($name) {
   $body = "Hello, $name. This HTTP triggered function executed successfully."
}

$urlscanhead = @{
   "Content-Type" = "application/json"
   "API-Key" = "URLSCANIO_APIKEY"
}
$urlscanbody = @{
   "url" = $url
   "visibility" = "public"
}
$urlscanbody = $urlscanbody | ConvertTo-Json
$res = Invoke-RestMethod -Method Post -Headers $urlscanhead -Body $urlscanbody -Uri "https://urlscan.io/api/v1/scan/"

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
   StatusCode = [HttpStatusCode]::OK    
   Body = $res.uuid
})

その結果をjsonパースしてUUIDを返り値として出力しています。

ここまで実装すると "urlscan_submissionuuid_CL" というテーブルに毎日調査結果(画面キャプチャ取得に使用するUUID)が保管されます。
スクリーンショット用のURLにUUIDをつけるようにKQLを書くと以下のように結果が出力できます。

urlscan_submissionuuid_CL
| where TimeGenerated > ago(30d)
| summarize arg_max(TimeGenerated, *) by url_s
| extend screenshot = strcat('https://urlscan.io/screenshots/', uuid_g, '.png')

画像5

メールで画面キャプチャ、ログイン試行ID、元のURLを送信する

HTML形式メールでimgタグを送るのですが、imgタグの<や>がエスケープされてしまうので、
コードビューを使って直接送信するメールのbodyを編集します。
送信にあたって件名にダミーのIDを付与しておきます。実際に③の実施の際に使用するIDですね。
今回はguid()で適当なランダム英数を持ってきて先頭10文字を取得したあとにハイフンを除いています。
宛先に使用するのはprotonmailを使います。(他のメールサービスだとスパムでこける可能性がある)

画像6

※GUIで見るとよくわからない表示になるのと、この表示に伴ってちょくちょくコードビュー上のコードが変わってしまうことがあるので要注意

画像7

画面キャプチャをスマホで確認する

それでは実際に送信されたメールを確認してみます。

画像8

画像9

いい感じです。
(テストで使用したフィッシングサイトは既にダウンしていましたが)
③の実施時には画面キャプチャを見て生きているサイトであれば、
スマホ用のOpen VPNからIPを秘匿化した上で実際のフィッシングサイトへアクセスし、
件名のダミーIDを入れて適当なパスワードを入れればOKです。

これで実際に運用に乗せられているか、他の課題は何か、はまた次回の投稿で。


この記事が気に入ったらサポートをしてみませんか?