DNS セキュリティ ポリシーと Sentinel
はじめに
Azure で DNS セキュリティー ポリシーという機能がパブリック プレビューになりました。こちらは、Azure DNS で名前解決する場合にフィルタすることができ、また診断設定で DNS クエリ ログを取得できるようになります。こちらの動作の確認と、Sentinel での活用方法を考えてみます。
設定
まず DNS セキュリティ ポリシーのリソースを作成する必要があります。以下のように作成画面でサブスクリプションやリソース グループ、インスタンス名、リージョンを指定します。
次に仮想ネットワークをリンクします。プライベート DNS ゾーンと同じようなイメージで、リンクした VNET にのみ、フィルタやログ取得の機能が適用されます。
次に DNS トラフィック規則 (フィルタ ルール) を設定します。後でも設定できるので、一旦ここは空のまま進めます。
最後に確認してデプロイに進みます。
リソース作成後に DNS トラフィック規則とドメイン リストを定義していきます。[DNS トラフィック規則] > [+追加] をクリックし、新規作成画面で [DNS ドメインの一覧の作成] をクリックします。
ドメイン リストの名前などを指定し、次ページで制御したいドメイン名を入力し、作成をクリックします。このドメイン リスト単位で許可・拒否を設定するため、異なるアクションを取りたいドメインは別のリストとして定義します。
DNS トラフィック規則の追加の画面に戻り、優先度・ルール名・トラフィック アクション (許可、ブロック、アラート) を設定し、保存します。
最後にログ取得のために診断設定を行います。他のリソースと同様に診断設定から DNS Response を選択し、保管先を設定します。
動作確認
まず通常の DNS クエリのログを確認してみます。以下のように Log Analytics ワークスペースでログが確認できます。送信元 IP やポート、クエリのドメイン名、回答など詳細が確認できます。
次にブロックの挙動を確認してみます。以下のように example.com は名前解決できますが、ブロックに設定した www.example.com は Server Failed になります。
ログで確認しても、Deny として記録されていました。
次にアラートを検証します。以下のように www.microsoft.com のドメイン リストを作成し、アラートで規則を作成します。
動作確認後のログが以下です。ResolverPolicyRuleAction に Alert と入る想定でしたが、None になっています。一旦ブロックに切り替えて、名前解決失敗を確認してからアラートに戻し、名前解決に成功することを確認の上、ログを見たのですが同様の結果でした。アラートに設定した場合の挙動が不明です。(分かりましたらアップデートします)
ちなみに明示的に許可した場合は Allow と入ります。
Sentinel でログを活用
Sentinel で DNS ログを扱う場合、ASIM が提供されています。しかしながら、新規機能である DNS セキュリティ ポリシー用はまだ未提供です。
そのため今回はカスタムの KQL クエリを検討していきます。代表的なユースケースは脅威インテリジェンスと DNS クエリのドメインを突き合わせて、一致する場合にインシデントとするものです。以下のサンプル クエリは分析ルール テンプレートの「TI map Domain entity to DnsEvents」 をベースに DNS セキュリティ ポリシー用に修正しました。こちらで脅威インテリジェンスにマッチする DNS クエリを特定することができ、分析ルールとして設定すれば不正な DNS クエリの実行をインシデントとして登録できます。
// 時間ベースのフィルターのルックバック期間を定義
let dt_lookBack = 1h; // DNSイベントの1時間を検索
let ioc_lookBack = 14d; // 脅威インテリジェンスの指標として 14 日間を検索
// ドメインに関連する脅威インテリジェンス指標の取得
let Domain_Indicators = ThreatIntelligenceIndicator
//ドメイン名のないインジケーターを除外
| where isnotempty(DomainName)
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| extend TI_DomainEntity = DomainName;
//脅威フィードで TLD のリストを作成し検証
let maxListSize = 100000;
let list_tlds = Domain_Indicators
| extend parts = split(DomainName, '.')
| extend tld = parts[(array_length(parts)-1)]
| summarize count() by tostring(tld)
| project tld
| summarize make_list(tld, maxListSize);
//ドメインインジケータと DNS イベント間の join を実行して、潜在的な悪意のあるアクティビティを特定
Domain_Indicators
| join kind=innerunique (
DNSQueryLogs
| where TimeGenerated > ago(dt_lookBack)
| extend Name = substring(QueryName, 0, strlen(QueryName) - 1) //末尾に [.] が含まれるため除外
| where isnotempty(Name)
| extend parts = split(Name, '.')
| extend tld = parts[(array_length(parts)-1)]
//脅威フィードの TLD のリストに TLD が含まれているかどうかを確認することで、解析されたドメインを検証
| where tld in~ (list_tlds)
| extend DNS_TimeGenerated = TimeGenerated
) on $left.TI_DomainEntity==$right.Name
//対応するインジケーターの有効期限が切れた後に発生した DNS イベントを除外
| where DNS_TimeGenerated < ExpirationDateTime
| summarize DNS_TimeGenerated = arg_max(DNS_TimeGenerated, *) by IndicatorId, Name
| project DNS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, SourceIpAddress, Name, QueryType, Type, TI_DomainEntity
| extend timestamp = DNS_TimeGenerated
また今回は検証できていませんが、Defender for Endpoint や Defender for Office365 などで発生したインシデントのエンティティにドメインが含まれていた場合、Logic Apps などを利用して DNS セキュリティ ポリシーに自動でブロックのルールを追加する、などの実装例も考えらえます。
まとめ
今回は DNS セキュリティ ポリシーの機能と Sentinel での活用例を検討・検証していきました。フィルタ、ログ取得ともにセキュリティ観点ではニーズのある機能になると思いますので、ぜひ活用を検討いただければと思います。ただし DNS クエリログは Web トラフィック ログと同様にログ サイズが大きくなる可能性があるため、検証を通して自環境のログの規模を確認いただくほうがよいと考えています。
Discussion