はじめに
Azure Bastion を利用して仮想マシンへリモート接続しているセッションのログ分析を行いたいと聞くことがある。例えば、高権限や機密データを取り扱うサーバー管理業務において、どのユーザーが、どのマシンへ、いつ、どこから接続したかを確認することでリスク検出を行いたいケースが該当する。
本記事では、公開ドキュメントに詳しく掲載されていない部分にフォーカスして、Azure Bastion リソースのログ分析方法の例を取り上げていく。
Azure Bastion は、ブラウザーと Azure portal を使用して安全かつシームレスに仮想マシンに接続できるようにするサービスである。RDP または SSH ポートの外部公開を制限し、仮想マシンを保護することが出来る。
以降の内容の前提条件は下記である。
- Windows か Linux の仮想マシンに対して Azure Bastion をデプロイ
- Azure Bastion の SKU は Basic で構成
- Log Analytics ワークスペースを作成しログ保存先として設定
- 作成した Log Analytics ワークスペースを Microsoft Sentinel へ接続
Azure Bastion からのリモート接続のログ取得
Azure Bastion リソースログを有効にすると、セッションのログ取得が可能となる。ログの保存先はいくつか選択肢があり、公開ドキュメントではストレージアカウントについて解説している。
本記事では、ログ分析基盤である Log Analytics へ保存した時にどのように表示・検索することができるかについて、実際に設定を行った時の操作感をお伝えし、Microsoft Sentinel での分析方法の例を提示する。
リソースログの有効化は上記のドキュメントの手順にある診断設定を行い、Log Analytics ワークスペースを事前に作成した上でログ送信の設定を行った。
診断設定を行った後で、しばらく時間が経つと Log Analytics ワークスペースへログが送信されたことが確認できた。
ログの個々のレコードの詳細を確認する際、各列の値について公開ドキュメントを参考にするとよいだろう。
下記の表へ、リファレンス からいくつかの説明をピックアップし、意訳して掲載しておく。
列 | 説明 |
---|---|
ClientIpAddress | Bastion から仮想マシンにログインするために使用されたブラウザーの IP アドレス |
ClientPort | Bastion から仮想マシンにログインするために使用されたブラウザーのポート番号 |
Duration | Bastion セッションが継続する時間 (ミリ秒) (セッションの切断時にのみ使用可能) |
Location | 要求を処理したサーバーの場所 (例: 米国中南部) |
OperationName | このイベントによって表される操作の名前(セッションの接続または切断) |
SessionEndTime | Bastion セッションが終了したときのタイムスタンプ (UTC) |
SessionStartTime | Bastion セッションが開始されたときのタイムスタンプ (UTC) |
TargetResourceId | Bastion が接続されていた仮想マシンの ResourceID |
TargetVMIPAddress | Bastion が接続されていた仮想マシンの IP アドレス |
個人的な気づきとして下記2点についても記しておく。
- ① SessionStartTime と SessionEndTime、および Duration などのセッション情報は Disconnect (切断)時のログにしか情報が載らない
- ② SessionEndTime についてのみ、時刻の表示形式をローカル時間へ変換できない(実装漏れのように感じるためフィードバック済)
Microsoft Sentinel によるログ分析
Azure Bastion リソースのログ分析方法の例として、「希有な Bastion 接続(Rare Bastion Connections)」を取り上げる。
下記の KQL による分析を行って、過去 14 日間の履歴にない新しい接続があったことを識別した。
この KQL は、Microsoft Sentinel にビルトインされているテンプレート「Rare RDP Connections」からアイデアを得て、Bastion 接続用にカスタマイズした。
let starttime = 14d;
let endtime = 1d;
MicrosoftAzureBastionAuditLogs
| where TimeGenerated > ago(endtime)
| where (OperationName == "Microsoft.Network/BastionHost/connect" and Message == "Successfully Connected.") or OperationName == "Microsoft.Network/BastionHost/disconnect"
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ConnectionCount = count()
by OperationName, UserName = tolower(UserName), ClientIpAddress, TargetVMIPAddress, Protocol, Location, Duration, SessionStartTime, SessionEndTime
| join kind=leftanti (
MicrosoftAzureBastionAuditLogs
| where TimeGenerated between (ago(starttime) .. ago(endtime))
| where (OperationName == "Microsoft.Network/BastionHost/connect" and Message == "Successfully Connected.") or OperationName == "Microsoft.Network/BastionHost/disconnect"
| summarize by UserName = tolower(UserName), ClientIpAddress, TargetVMIPAddress
)on UserName, ClientIpAddress, TargetVMIPAddress
| summarize StartTime = min(StartTime), EndTime = max(EndTime), ConnectionCount = sum(ConnectionCount)
by OperationName, UserName, ClientIpAddress, TargetVMIPAddress, Protocol, Location, Duration, SessionStartTime, SessionEndTime
-
Rare Bastion Connections を手動実行した時のサンプル
Microsoft Sentinel の分析ルールを作成すれば、KQL の自動実行のスケジューリングと結果に応じたインシデントの起票が可能となる。 -
作成した分析ルール Rare Bastion Connections の設定変更画面
起票されたインシデントは Azure 管理ポータルから確認可能であるだけでなく、担当割り当てやステータスなどの運用・調査のための項目が存在する。更に自動応答・通知と組み合われば、セキュリティ運用の自動化に近づくだろう。
まとめ
- Azure Bastion からの希有なリモート接続を検出する手法の紹介
- Azure Bastion のリソースログを Log Analytics へ保存した時にどのように表示・検索することができるかについて、実際に設定を行った時の操作感の解説
- Microsoft Sentinel のテンプレートを応用した分析ルールを設定し、想定通りにインシデントを起票できたことを確認