Datadog SECL は、Datadog Workload Protection 内で Agent 式やポリシーを作成するときに使用されるカスタムドメイン固有言語です。セキュリティチームは SECL を使用して、条件や演算子、またはセキュリティエージェントがホスト、コンテナ、アプリケーション、クラウドインフラストラクチャー全体で監視できるパターンを指定してリアルタイムの脅威検出ルールを定義できます。

SECL ルールの仕組み

SECL はローカルフィルターのようなものです。各ホスト上の Agent 内で実行され、カーネルイベントや OS イベントを監視します。イベントが SECL 式と一致すると、Agent は検知を報告します。

Datadog の脅威検出ルールはバックエンドロジックとして機能します。このルールは (@agent.rule_id を使用して) 1 つ以上の Agent ルールを組み合わせ、しきい値を追加し、ノイズを抑制し、アラートのルーティング方法を決定します。

要約すると、Agent ルールは未加工の動作を検出し、検出ルールはそれをエンドツーエンドの攻撃ストーリーに変えます。

このガイドではルール式を手動で作成する方法を説明しますが、Workload Protection には、Agent ルールと検出ルールを同時に作成する手順を案内する [Assisted rule creator] (ルール作成支援機能) ウィザードも用意されています。カスタム Agent ルールと検出ルールを同時に作成するを参照してください。

SECL 式の構文

SECL 式の標準的な形式は次のとおりです。

<event-type>.<event-attribute> <operator> <value> [<operator> <event-type>.<event-attribute>] ...

この形式を用いた Linux システム向けの例となるルールは、次のようになります。

open.file.path == "/etc/shadow" && process.file.path not in ["/usr/sbin/vipw"]

演算子

SECL 演算子は、イベント属性を組み合わせて完全な式を作成するために使用されます。以下の演算子が利用可能です。

SECL 演算子定義Agent バージョン
==等しい7.27
!=等しくない7.27
>大なり7.27
>=以上7.27
<小なり7.27
<=以下7.27
! または not否定7.27
^バイナリ否定7.27
in [elem1, ...]要素がリストに含まれている7.27
not in [elem1, ...]要素がリストに含まれていない7.27
=~一致する文字列7.27
!~一致しない文字列7.27
&バイナリ AND7.27
|バイナリ OR7.27
&& または and論理 AND7.27
|| または or論理 OR7.27
in CIDR要素が IP 範囲にある7.37
not in CIDR要素が IP 範囲にない7.37
allin CIDRすべての要素が IP 範囲にある7.37
in [CIDR1, ...]要素が IP 範囲にある7.37
not in [CIDR1, ...]要素が IP 範囲にない7.37
allin [CIDR1, ...]すべての要素が IP 範囲にある7.37

パターンと正規表現

SECL 式ではパターンまたは正規表現を使用できます。これらは in、not in、=~、および !~ 演算子とともに使用できます。

形式例サポート対象フィールドAgent のバージョン
~"pattern"~"httpd.*"All7.27
r"regexp"r"rc[0-9]+"次を除くすべて: .path7.27

.path フィールドのパターンは Glob として使用されます。* は同じレベルのファイルやフォルダに一致します。7.34 で導入された ** は、すべてのファイルとサブフォルダに一致させるためにパスの末尾に使用できます。

期間

SECL を使用して期間に基づくルールを作成できます。これは、特定の期間中に発生するイベントに対してトリガーされます。たとえば、プロセスを作成してから一定時間が経過した後でシークレットファイルへのアクセスがあったイベントでトリガーします。 このようなルールは次のように記述できます。

open.file.path == "/etc/secret" && process.file.name == "java" && process.created_at > 5s

期間は単位サフィックスが付いた数値です。サポートされているサフィックスは “s”、“m”、“h” です。

プラットフォーム固有の構文

SECL 式は複数のプラットフォームをサポートしています。以下のドキュメントを参照して、各プラットフォームで使用可能な属性とヘルパーを確認できます。

ルール作成のヒント

  • 常にオペレーティングシステム (OS) を設定します。
  • ノイズを減らすため、祖先にアンカーを設定します。process.ancestors.file.name を使用します。
  • 期間 (例: > 5s、10m、2h) を使用して短い実行ウィンドウをターゲットにします。
  • 可能な限り完全一致 (==) を使用します。これにより、ノイズが最も少なくなります。
  • リストメンバーシップ (in [...]) は、許可リストや制御された値セットに最適です。
  • パスファミリーには glob 一致 (~"/path/*") を使用します。これは正規表現よりも安全で高速です。
  • glob やリストが使用できない場合にのみ、正規表現 (=~) を使用してください。正規表現は可能な限り限定的にしてください。目安として、== または in [...] から始めてください。正規表現は最後の手段としてのみ使用してください。
  • 否定 (not in [...]、!~) を使用して、例外 (信頼できるツールなど) を明示的に除外します。
  • ネットワーク境界には CIDR 演算子 (in CIDR、not in CIDR) を使用します。
  • ルールには動作に基づいた名前を付けます。形式は What + Who + Context に従います。
  • 十分にタグ付けします (team、app、env、MITRE、severity)。

一般的な誤りを避けてください

パターン説明
open.file.path == "/etc/passwd"、exec.comm != ""広すぎます。多数の有効なユースケースに一致します。
container.id != ""より具体的なフィールドでスコープを絞った場合にのみ有用です。

ライブラリの例

より詳細な例については、Agent に標準で同梱されているデフォルトポリシーを参照してください。Workload Protection のデフォルトポリシーを参照してください。

Agent ポリシーファイルでは、各ルールに id と expression が含まれています。オプションの actions を追加することもできます。詳細については、変数とアクション を参照してください。

Linux

機密ファイルへのアクセス (安全なツールを許可リストに登録)

rules:
  - id: access_sensitive_files
    expression: >-
      open.file.path in ["/etc/shadow", "/etc/sudoers"] &&
      process.file.path not in ["/usr/sbin/vipw", "/usr/sbin/visudo"]
    filters:
      - os == "linux"

bash を起動する NGINX または PHP

rules:
  - id: nginx_php_spawn_bash
    expression: >-
      exec.file.path == "/usr/bin/bash" &&
      (
        process.ancestors.file.name == "nginx" ||
        process.ancestors.file.name =~ "php*"
      )
    filters:
      - os == "linux"

コンテナからの不審な IMDS アクセス

rules:
  - id: suspicious_imds_access
    expression: >-
      connect &&
      network.destination.ip in ["169.254.169.254"] &&
      container.id != ""
    filters:
      - os == "linux"

メンテナンスウィンドウ外でのカーネルモジュールのロード

rules:
  - id: kernel_module_load
    expression: >-
      load_module &&
      process.user != "root" &&
      process.ancestors.file.name not in ["modprobe", "insmod"]
    filters:
      - os == "linux"

起動直後の機密ファイルの読み取り

rules:
  - id: sensitive_file_read_after_start
    expression: >-
      open.file.path == "/etc/secret" &&
      process.file.name == "java" &&
      process.created_at > 5s
    filters:
      - os == "linux"

企業外 IP へのアウトバウンド通信 (CIDR 許可リスト)

rules:
  - id: outbound_non_corporate_ips
    expression: >-
      connect &&
      network.destination.ip not in [10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12]
    filters:
      - os == "linux"

Windows

実行キーによるレジストリの永続化

rules:
  - id: registry_run_key_persistence
    expression: >-
      set_key_value &&
      open_key.registry.key_path =~ "*\\Software\\Microsoft\\Windows\\CurrentVersion\\Run*"
    filters:
      - os == "windows"

署名のないバイナリによる PowerShell の起動

rules:
  - id: unsigned_binary_powershell
    expression: >-
      exec.file.path =~ "*\\WindowsPowerShell\\v1.0\\powershell.exe" &&
      process.parent.file.path !~ "*\\Program Files*" &&
      process.user_sid != "S-1-5-18"
    filters:
      - os == "windows"

クロスプラットフォーム

暗号通貨マイナーのインジケーター

rules:
  - id: crypto_miner_indicators
    expression: >-
      exec.args_flags in ["cpu-priority", "donate-level", ~"randomx-1gb-pages"] ||
      exec.args in [~"*stratum+tcp*", ~"*nicehash*", ~"*yespower*"]