複合検出ルールを作成する

以下でサポートされています。

このドキュメントでは、Google Security Operations プラットフォーム内で複合ルールを構築する方法について技術的なガイダンスを提供します。このプロセスでは、複数の YARA-L 2.0 ルールを接続して、複雑な攻撃パターンを特定します。複合検出はマルチイベント ルールとして構造化され、標準の単一イベント ルールと同じ基本的な構文が維持されます。詳細については、複合検出の概要をご覧ください。

ルールの構造を理解する

複合検出ルールは常にマルチイベント ルールであり、単一イベント ルールと同じ構造と構文に従います。

複合ルールには、次の重要なコンポーネントがあります。

  • events セクション: 入力(ルールが分析する特定の検出またはイベント)を定義します。

  • match セクション: 定義された時間枠で入力を接続する方法を指定します。

  • condition セクション: 結合されたイベントがアラートをトリガーする基準を満たしているかどうかを判断する最終的なロジックが含まれています。

events セクションで入力を定義する

複合検出ルールを構築する最初の手順は、events セクションでルールの入力を定義することです。複合ルールの入力は、他のクエリで生成された検出を保存するコレクションから取得されます。Google SecOps には、コレクションからデータにアクセスする次の 2 つの方法があります。

変数またはメタラベルを使用して検出コンテンツを参照する

元の UDM イベントを参照せずに検出からデータにアクセスするには、outcome 変数、match 変数、または meta ラベルを使用します。このアプローチは、柔軟性が高く、さまざまなルールタイプ間の互換性が高いため、おすすめです。

たとえば、複数のルールで、さまざまなコンテキストで検索する文字列(URL、ファイル名、レジストリキーなど)を共通の outcome 変数に保存できます。複合ルールからこの文字列にアクセスするには、detection で始まり、コレクション リソースの要素を使用して関連情報を特定します。

例: 検出ルールで次の情報が生成されるとします。

  • 結果変数: dest_domain = "cymbal.com"

  • UDM フィールド: target.hostname = "cymbal.com"

複合ルールでは、次のパスを使用してこのデータにアクセスできます。

  • detection.detection.variables["dest_domain"].string_val を使用して dest_domain 結果変数にアクセスします。

  • target.hostname UDM フィールドにアクセスする detection.collection_elements.references.event.target.hostname

  • detection.time_window.start_time.seconds を使用して、検出の開始タイムスタンプにアクセスします。

Collection API と SecurityResult API は、両方へのアクセスを提供します。

  • 検出メタデータと結果の値(detection.detection
  • 参照されたルールからの基盤となる UDM イベント(collection_elements

ルール ID または名前で検出コンテンツを参照する

ルールは、名前または ID で参照できます。このアプローチは、検出ロジックが特定のルールに依存しており、分析するデータをそれらのルールの結果のみに減らしたい場合に推奨されます。名前または ID で関連するルールを参照すると、分析されるデータが削減されるため、パフォーマンスが向上し、タイムアウトが防止されます。たとえば、既知の以前の検出から target.urlprincipal.ip などのフィールドを直接クエリできます。

  • ルール ID でルールを参照する(推奨): detection.detection.rule_id フィールドを使用して、ID でルールを参照します。ルール ID は、Google SecOps のルールの URL で確認できます。ユーザーが作成したルールの ID は ru_UUID 形式ですが、キュレーテッド検出の ID は ur_UUID 形式です。次に例を示します。

    detection.detection.rule_id = "ru_e0d3f371-6832-4d20-b0ad-1f4e234acb2b"

  • ルール名でルールを参照する: detection.detection.rule_name フィールドを使用して、名前でルールを参照します。正確なルール名を指定することも、正規表現を使用して照合することもできます。次に例を示します。

    • detection.detection.rule_name = "My Rule Name"
    • detection.detection.rule_name = "/PartOfName/"

match セクションで入力を結合する

複合ルールで関連する検出、イベント、エンティティを接続するには、events セクションで定義された変数を使用して match セクションを定義します。これらの変数には、ルールラベル、結果変数、一致変数、検出フィールド、コレクション要素などがあります。

構文については、一致セクションの構文をご覧ください。

複合ルール: 時間間隔とホップ ウィンドウ

複合ルールは、単一の時点ではなく、時間間隔に対して検出とイベントを照合します。入力検出時間枠がそのホップ ウィンドウと重複する場合(たとえば、アクティビティがその時間ブロック中にアクティブだった場合)、複合ホップ ウィンドウと一致します。

検出が隣接するホップ ウィンドウ間の境界にまたがっている場合(パイプラインの遅延により、これらの過去の一致が後で表示される)、1 つの検出で複数のアラートがトリガーされることがあります。具体的には、入力検出時間枠(WindowStart から WindowEnd)がホップ ウィンドウと重複する場合、複合ルール ホップ ウィンドウは一致をトリガーします。

次に例を示します。

  1. 複合ルールには 60 分のホップ ウィンドウ(ホップ 1(18:58 ~ 19:58)、ホップ 2(19:58 ~ 20:58))があります。
  2. 上流プロデューサーの検出のウィンドウは 19:57:54 ~ 20:56:54(59 分間)です。
  3. プロデューサー ウィンドウは 19:57:54(ホップ 1 の終了 6 秒前)に開始し、20:56:54(ホップ 2 の間)に終了するため、両方のホップ ウィンドウと重複します。
  4. これにより、2 つの複合検出(ホップ 1 用とホップ 2 用)がトリガーされ、偽陰性の防止に役立ちます。プロデューサー ルールが重複で一致しなかった場合、部分的に重複する検出はホップ 1 またはホップ 2 のいずれでも考慮されず、検出と他のイベントの相関関係が見逃されます。

ホップ ウィンドウの指定方法の詳細と例については、ホップ ウィンドウをご覧ください。

condition セクションを定義する

match セクションの結果を評価する condition セクションを定義します。条件が true の場合、アラートが生成されます。構文については、条件セクションの構文をご覧ください。

複合ルールに高度な手法を適用する

このセクションでは、複合ルールを構築する際に高度な手法を適用する方法について説明します。

イベントと検出を組み合わせる

複合ルールでは、UDM イベント、エンティティ グラフデータ、検出フィールドなど、複数のデータソースを組み合わせることができます。次のガイドラインが適用されます。

  • ソースごとに個別の変数を使用する: 各データソース(イベント、エンティティ、検出を含む)に一意のイベント変数(イベントの場合は $e、検出の場合は $d など)を割り当てます。

  • 共有コンテキストでソースを結合する: ルールの条件で、ユーザー ID、IP アドレス、ドメイン名などの共通の値を使用してデータソースを接続します。

  • 一致時間枠を定義する: 48 時間以下の時間枠で match 句を必ず含めます。

例: イベントと検出を組み合わせる

rule CheckCuratedDetection_with_EDR_and_EG {
  meta:
    author = "noone@cymbal.com"
  events:
    $d.detection.detection.rule_name = /SCC: Custom Modules: Configurable Bad Domain/
    $d.detection.collection_elements.references.event.network.dns.questions.name = $domain
    $d.detection.collection_elements.references.event.principal.asset.hostname = $hostname

    $e.metadata.log_type = "LIMACHARLIE_EDR"
    $e.metadata.product_event_type = "NETWORK_CONNECTIONS"
    $domain = re.capture($e.principal.process.command_line, "\\s([a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+)$")
    $hostname = re.capture($e.principal.hostname, "([^.]*)")

    $prevalence.graph.metadata.entity_type = "DOMAIN_NAME"
    $prevalence.graph.metadata.source_type = "DERIVED_CONTEXT"
    $prevalence.graph.entity.hostname = $domain
    $prevalence.graph.entity.domain.prevalence.day_count = 10
    $prevalence.graph.entity.domain.prevalence.rolling_max <= 5
    $prevalence.graph.entity.domain.prevalence.rolling_max > 0

  match:
    $hostname over 1h

  outcome:
    $risk_score = 80
    $CL_target = array($domain)

  condition:
    $e and $d and $prevalence
}

順次複合検出を作成する

シーケンシャル複合検出では、ブルート フォース ログイン試行の検出に続いてログインが成功するなど、検出の順序が重要な関連イベントのパターンを特定します。これらのパターンでは、複数のベース検出、未加工の UDM イベント、またはその両方を組み合わせることができます。

順次複合検出を作成するには、ルール内でその順序を適用する必要があります。期待されるシーケンスを適用するには、次のいずれかの方法を使用します。

  • スライディング ウィンドウ: match 条件でスライディング ウィンドウを使用して、検出のシーケンスを定義します。

  • タイムスタンプの比較: ルールロジック内の検出のタイムスタンプを比較して、選択した順序で発生していることを確認します。

例: 連続する複合検出

events:
    $d1.detection.detection.rule_name = "fileEvent_rule"
    $userid = $d1.detection.detection.variables["user"].string_val
    $hostname = $d1.detection.detection.variables["hostname"].string_val

    $d2.detection.detection.rule_name = "processExecution_rule"
    $userid = $d2.detection.detection.variables["user"].string_val
    $hostname = $d2.detection.detection.variables["hostname"].string_val

    $d3.detection.detection.rule_name = "networkEvent_rule"
    $userid = $d3.detection.detection.variables["user"].string_val
    $hostname = $d3.detection.detection.variables["hostname"].string_val

$d3.detection.collection_elements.references.event.metadata.event_timestamp.seconds > $d2.detection.collection_elements.references.event.metadata.event_timestamp.seconds

  match:
    $userid over 24h after $d1

さらにサポートが必要な場合 コミュニティ メンバーや Google SecOps のプロフェッショナルから回答を得ることができます。