
Google Chronicle Curated Detections のチューニングとリファクタリングにより、アラート疲れを解消し、ロジックのギャップやバグを修正します。
このリポジトリは、ネイティブな Google SecOps (Chronicle) キュレーション検出ルール に関するアーキテクチャ設計上の欠陥、ロジックの不整合、チューニング戦略を文書化したものです。
Google Threat Intelligence (GTIG) は優れた概念的な脅威カバレッジ(APT29/BRICKSTORM キャンペーンの追跡など)を提供していますが、キュレーションルールの生の YARA-L 実装は、グルーピングロジックの矛盾やハードコードされた閾値変数といった実装上の見落としにしばしば悩まされます。実際の企業環境では、これが頻繁に大規模なアラート疲れを引き起こします。
本プロジェクトは、ネイティブルールがなぜ壊れるのか、あるいは SOC をアラートで溢れさせるのかを分析し、これらの問題を解決するための最適化されたカスタムルールとパッチを共有します。
Google は、侵害されたサービスプリンシパルによる Microsoft 365 Exchange Online からの大量メール持ち出しを検出するための一連のルールをリリースしました(APT29/Midnight Blizzard が多用する手法)。
影響を受けるキュレーションルールは以下のとおりです:
O365 Mailbox Access by Service Principal with Multiple User AgentsO365 Multiple Mailboxes Accessed by Service PrincipalO365 Mailbox Access by Service Principal from Multiple ASNsO365 Multiple Mailboxes Accessed via Microsoft Graph APIこの一連のルールには、おそらくルールパック全体でのコード再利用に起因する、表明された目的と YARA-L 実装との間の体系的なロジックの不一致が含まれています。これらのルールは、自動化されたサービスプリンシパルと通常の人間のアクティビティを適切に区別できておらず、その結果、通常の従業員の行動でアラートが発報されます。
ルールの説明には明示的に 「単一の O365 セッション ID を持つサービスプリンシパルを検出する...」 と記載されているにもかかわらず、「Multiple User Agents」ルールの YARA-L match セクションは、セッション ID($session_id)ではなく $application_id でグルーピングしています。これはルールの表明された目的と完全に矛盾しています。
このルールは、特定の ClientAppId に紐づく異常な行動パターン(IP、ASN、User-Agent の変更)を追跡します。Google は複数のネイティブ Microsoft アプリケーション向けの除外正規表現を含めていますが、最も普及している人間向けモバイルクライアントである Microsoft Outlook Mobile App(27922004-5251-4030-b22d-91ecd9a37ea4)を不可解にも除外していません。
Multiple ASNs アラートが発生します。また、異なる従業員が iOS と Android を使って同じ部門メールボックスを確認すると、Multiple User Agents アラートが発生します。バックエンドのサービスアカウントを識別するため、Google のロジックは次の条件に依存しています:
$e.principal.user.userid != $e.target.user.userid
[email protected] を開く場合)にとっても標準的な動作です。この設計上の欠陥は、通常の運用における人間のトラフィックに対して大量のノイズを生成します。これらの設計上の欠陥を修正するには、運用上のニーズに応じて 2 つの選択肢があります:
オプション 1: ネイティブ SIEM 除外(クイックフィックス)
必ずしもルールを無効化したりカスタムコードを書いたりする必要はありません。Google SecOps SIEM の UI 内で直接 除外 を作成するだけで済みます。Outlook Mobile(27922004-5251-4030-b22d-91ecd9a37ea4)および承認済みのバックアップアプリケーション(例:Keepit)の ClientAppId を対象とする除外を追加するだけです。これにより、Google がキュレーションしたルールを有効なままにしつつ、誤検知の洪水を即座に止めることができます。
オプション 2: カスタムルールのデプロイ(アーキテクチャ上の修正)
基盤となるグループ化ロジックの欠陥($application_id の不一致など)を完全に修正したい場合は、キュレーションされた検出を無効化し、カスタムルールをデプロイする必要があります。修正内容は次のとおりです:
27922004-...)を明示的にホワイトリストに登録する。match セクションを修正し、セッションごとに適切に集約する。rule custom_ttp_o365_mailbox_access_by_service_principal_with_multiple_uas {
meta:
rule_name = "[CUSTOM] O365 Mailbox Access by Service Principal with Multiple User Agents"
description = "Detects a Service Principal with a single O365 session ID accessing O365 mailboxes with multiple user agents. Tuned to fix grouping logic and exclude Outlook Mobile (Public Client) human traffic."
severity = "Low"
tactic = "TA0009"
technique = "T1114.002"
events:
$e.metadata.log_type = "OFFICE_365"
$e.metadata.product_event_type = "MailItemsAccessed" nocase
$e.target.application = "Exchange"
$e.security_result.detection_fields["RecordType"] = /^(2|50)$/
// Extract actual Session ID and App ID
$session_id =$e.network.session_id
$application_id =$e.additional.fields["ClientAppId"]
$e.principal.user.userid !=$e.target.user.userid
(
$e.network.http.user_agent = /AppId/ nocase or$e.additional.fields["ClientAppId"] = /./
)
// EXCLUSIONS: Added Outlook Mobile + Standard Google Exclusions
$e.additional.fields["ClientAppId"] != /^(27922004-5251-4030-b22d-91ecd9a37ea4|bea75f7a-2505-46e8-9bf6-d3f7da9c9da7|b52893c8-bc2e-47fc-918b-77022b299bbc|...)$/ nocase
match:
// Group by both App AND Session to isolate the specific token lifecycle
$application_id,$session_id over 3h
outcome:
$vendor_name = "Microsoft"
$product_name = "Office 365"
$source_ua_dc = count_distinct($e.network.http.user_agent)
$client_app_id = array_distinct($e.additional.fields["ClientAppId"])
condition:
// Triggers if the SAME session rotates 2+ User Agents
$e and $source_ua_dc >= 2
}
(ロジックは同じですが、除外設定では Outlook Mobile と並んで Keepit (a7cd46df...) のような承認済みバックアップソリューションを必ずホワイトリストに登録してください。)
(User Agents ルールとは異なり、Google はこのルールで $session_id によるグループ化を正しく行えています。ただし、Outlook Mobile の除外が依然として欠けています。上記と同じ除外ロジックに従い、$source_asn_dc >= 2 の条件を維持してください。)
(ロジックは同じです。events ブロックの末尾にある除外正規表現に、Keepit (a7cd46df...) のような承認済みバックアップアプリケーションを必ず追加してください。)
ルール: ttp_o365_teams_external_impersonation_attempt
対象イベント: OFFICE_365 (metadata.product_event_type = "TeamsImpersonationDetected")
Microsoft Defender for Office 365 は、外部からの受信 Microsoft Teams チャットを検査し、TeamsImpersonationDetected 監査操作を通じてドメインやブランドのなりすましの可能性をフラグ付けします。YARA-L 検出ルールに変換すると、ネイティブのキュレーション済み実装はエンティティの誤帰属とマッチキーの見落としという問題を抱えています。
// Native Flawed Implementation Sample
events:
$e.metadata.log_type = "OFFICE_365"
$e.metadata.product_event_type = /TeamsImpersonationDetected/ nocase
$principal_userid =$e.principal.user.userid
match:
$principal_userid over 1h
outcome:
$result = "succeeded"
$adversary_name = array_distinct($e.principal.user.userid)
Chronicle のデフォルトパーサーは、受信者 UserId(メッセージを受信した内部ユーザー)を principal.user.userid にマッピングします。なりすましを試みる外部アクターは、ネストされた Sender オブジェクト(Sender.UPN)内に存在し、additional.fields["Sender_UPN"] にパースされます。
$adversary_name = array_distinct($e.principal.user.userid) を割り当てることで、このルールは下流の SOC アラートおよび SOAR ケースにおいて内部の被害者を攻撃者としてラベル付けします。このルールは match: $principal_userid over 1h を強制し、アラートを受信従業員ごとにグループ化します。
オプション 1: アラートプロファイルの調整(クイックフィックス)