YARA-L 2.0 語言總覽

支援的國家/地區:

YARA-L 2.0 是一種電腦語言,用於建立搜尋企業記錄檔資料的規則,並會將這些資料擷取至您的 Google Security Operations 執行個體。YARA-L 語法衍生自 VirusTotal 開發的 YARA 語言。這項語言可與 Google SecOps 偵測引擎搭配使用,讓您在大量資料中搜尋威脅和其他事件。

如要瞭解詳情,請參考下列資源:

YARA-L 2.0 規則範例

以下範例顯示以 YARA-L 2.0 編寫的規則。兩者都示範如何在規則語言中關聯事件。

規則和調整

下列規則會檢查事件資料中的特定模式,並在找到模式時建立偵測結果。這項規則包含用於追蹤事件類型和 metadata.event_type UDM 欄位的變數 $e1。這項規則會檢查規則運算式是否與 e1 相符。當發生 $e1 事件時,系統會建立偵測結果。規則中包含 not 條件,可排除特定非惡意路徑。 您可以新增 not 條件,避免發生偽陽性。

rule suspicious_unusual_location_svchost_execution
{

 meta:
   author = "Google Cloud Security"
   description = "Windows 'svchost' executed from an unusual location"
   yara_version = "YL2.0"
   rule_version = "1.0"

 events:

   $e1.metadata.event_type = "PROCESS_LAUNCH"
   re.regex($e1.principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
   not re.regex($e1.principal.process.command_line, `\\Windows\\System32\\`) nocase

condition:

   $e1
}

來自不同城市的登入事件

下列規則會搜尋在不到 5 分鐘內,從兩個以上城市登入企業的使用者:

rule DifferentCityLogin {
  meta:

  events:
    $udm.metadata.event_type = "USER_LOGIN"
    $udm.principal.user.userid = $user
    $udm.principal.location.city = $city

  match:
    $user over 5m

  condition:
    $udm and #city > 1
}

比對變數$user

事件變數$udm

預留位置變數$city$user

這項規則的運作方式如下:

  • 群組事件 (含使用者名稱 $user),並在找到相符項目時傳回該事件 ($user)。
  • 時間間隔為 5 分鐘,也就是說,只有間隔不到 5 分鐘的事件會相互關聯。
  • 搜尋事件類型為 USER_LOGIN 的事件群組 ($udm)。
  • 針對該事件群組,規則會將使用者 ID 呼叫為 $user,登入城市則呼叫為 $city.
  • 如果事件群組 ($udm) 在 5 分鐘時間範圍內,city 值的相異數量 (以 #city 表示) 大於 1,則傳回相符項目。

快速建立及刪除使用者

下列規則會搜尋在 4 小時內建立然後刪除的使用者:

rule UserCreationThenDeletion {
  meta:

  events:
    $create.target.user.userid = $user
    $create.metadata.event_type = "USER_CREATION"

    $delete.target.user.userid = $user
    $delete.metadata.event_type = "USER_DELETION"

    $create.metadata.event_timestamp.seconds <=
       $delete.metadata.event_timestamp.seconds

  match:
    $user over 4h

  condition:
    $create and $delete
}

事件變數$create$delete

比對變數$user

預留位置變數:不適用

這項規則的運作方式如下:

  • 群組事件 (含使用者名稱 $user),並在找到相符項目時傳回該事件 ($user)。
  • 時間範圍為 4 小時,也就是說,只有間隔不到 4 小時的事件會相互關聯。
  • 搜尋兩個事件群組 ($create$delete,其中 $create 等於 #create >= 1)。
  • $create 對應於 USER_CREATION 事件,並將使用者 ID 呼叫為 $user
  • $user 用於彙整這兩組事件。
  • $delete 對應於 USER_DELETION 事件,並將使用者 ID 呼叫為 $user。這項規則會尋找兩個事件群組中使用者 ID 相同的相符項目。
  • 這項規則會尋找 $delete 事件發生時間晚於 $create 事件的情況,並在發現時傳回相符項目。

單一事件規則

單一事件規則是指與單一事件相關的規則。單一事件規則可以是:

  • 沒有比對部分的任何規則。
  • 規則包含 match 區段和 condition 區段,且只檢查 1 個事件是否存在 (例如「$e」、「#e > 0」、「#e >= 1」、「1 <= #e」、「0 < #e」)。

舉例來說,下列規則會搜尋使用者登入事件,並傳回 Google SecOps 帳戶中儲存的企業資料內,第一個遇到的事件:

rule SingleEventRule {
  meta:
    author = "noone@altostrat.com"

  events:
    $e.metadata.event_type = "USER_LOGIN"

  condition:
    $e
}

以下是另一個單一事件規則範例,其中包含相符區段。這項規則會搜尋在 5 分鐘內登入至少一次的使用者。這項檢查會確認使用者登入事件是否確實存在。

rule SingleEventRule {
  meta:
    author = "alice@example.com"
    description = "windowed single event example rule"

  events:
    $e.metadata.event_type = "USER_LOGIN"
    $e.principal.user.userid = $user

  match:
    $user over 5m

  condition:
    #e > 0
}
rule MultiEventRule{
  meta:
    author = "alice@example.com"
    description = "Rule with outcome condition and simple existence condition on one event variable"

  events:
    $e.metadata.event_type = "USER_LOGIN"
    $e.principal.user.userid = $user

  match:
    $user over 10m

  outcome:
    $num_events_in_match_window = count($e.metadata.id)

  condition:
    #e > 0 and $num_events_in_match_window >= 10 // Could be rewritten as #e >= 10
}

多個事件規則

使用多個事件規則,將指定時間範圍內的許多事件分組,並嘗試找出事件之間的關聯性。一般來說,多重事件規則會包含下列項目:

  • match 區段,指定事件分組的時間範圍。
  • condition 區段:指定應觸發偵測的條件,並檢查是否存在多個事件。

舉例來說,下列規則會搜尋在 10 分鐘內登入至少 10 次的使用者:

rule MultiEventRule {
  meta:
    author = "noone@altostrat.com"

  events:
    $e.metadata.event_type = "USER_LOGIN"
    $e.principal.user.userid = $user

  match:
    $user over 10m

  condition:
    #e >= 10
}

IP 位址範圍內的單一事件

以下範例顯示單一事件規則,用於搜尋兩個特定主機名稱和特定 IP 位址範圍之間的相符項目:

rule OrsAndNetworkRange {
  meta:
    author = "noone@altostrat.com"

  events:
    // Checks CIDR ranges.
    net.ip_in_range_cidr($e.principal.ip, "203.0.113.0/24")

    // Detection when the hostname field matches either value using or.
    $e.principal.hostname = /pbateman/ or $e.principal.hostname = /sspade/

  condition:
    $e
}

任何和所有規則範例

下列規則會搜尋登入事件,其中所有來源 IP 位址在 5 分鐘的時間範圍內,都不符合已知安全的 IP 位址。

rule SuspiciousIPLogins {
  meta:
    author = "alice@example.com"

  events:
    $e.metadata.event_type = "USER_LOGIN"

    // Detects if all source IP addresses in an event do not match "100.97.16.0"
    // For example, if an event has source IP addresses
    // ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
    // it will be detected since "100.97.16.1", "100.97.16.2",
    // and "100.97.16.3" all do not match "100.97.16.0".

    all $e.principal.ip != "100.97.16.0"

    // Assigns placeholder variable $ip to the $e.principal.ip repeated field.
    // There will be one detection per source IP address.
    // For example, if an event has source IP addresses
    // ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
    // there will be one detection per address.

    $e.principal.ip = $ip

  match:
    $ip over 5m

  condition:
    $e
}

規則中的規則運算式

下列 YARA-L 2.0 規則運算式範例會搜尋收到來自 altostrat.com 網域電子郵件的事件。由於 nocase 已新增至 $host 變數 regex 比較和 regex 函式,因此這兩項比較都不會區分大小寫。

rule RegexRuleExample {
  meta:
    author = "noone@altostrat.com"

  events:
    $e.principal.hostname = $host
    $host = /.*HoSt.*/ nocase
    re.regex($e.network.email.from, `.*altostrat\.com`) nocase

  match:
    $host over 10m

  condition:
    #e > 10
}

複合規則範例

複合偵測項目會使用複合規則,進一步強化威脅偵測功能。 這些複合規則會使用其他規則的偵測結果做為輸入內容。這樣一來,就能偵測出個別規則可能無法偵測到的複雜威脅。詳情請參閱複合式偵測總覽

絆線偵測

Tripwire 複合偵測項目是最簡單的複合偵測項目,可對偵測結果中的欄位執行作業,例如結果變數或規則中繼資料。這些條件有助於篩選偵測結果,找出可能代表高風險的狀況,例如管理員使用者或正式環境。

rule composite_admin_detection {
  meta:
    rule_name = "Detection with Admin User"
    author = "Google Cloud Security"
    description = "Composite rule that looks for any detections where the actor is an admin user"
    severity = "Medium"

  events:
    $rule_name = $d.detection.detection.rule_name
    $principal_user = $d.detection.detection.outcomes["principal_users"]
    $principal_user = /admin|root/ nocase

  match:
    $principal_user over 1h

  outcome:
    $risk_score = 75
    $upstream_rules = array_distinct($rule_name)

  condition:
    $d
}

門檻和匯總偵測

匯總複合式偵測規則可讓您根據共用屬性 (例如主機名稱或使用者名稱) 將偵測結果分組,並分析匯總資料。以下是常見用途:

  • 找出產生大量安全性快訊或匯總風險的使用者。
  • 彙整相關偵測結果,偵測具有異常活動模式的主機。

風險匯總範例:

rule composite_risk_aggregation {
  meta:
    rule_name = "Risk Aggregation Composite"
    author = "Google Cloud Security"
    description = "Composite detection that aggregates risk of a user over 48 hours"
    severity = "High"

  events:
    $rule_name = $d.detection.detection.rule_name
    $principal_user = $d.detection.detection.outcomes["principal_users"]
    $risk = $d.detection.detection.risk_score

  match:
    $principal_user over 48h

  outcome:
    $risk_score = 90
    $cumulative_risk = sum($risk)
    $principal_users = array_distinct($principal_users)
    $upstream_rules = array_distinct($rule_name)

  condition:
    $d and $cumulative_risk > 500
}

策略匯總範例:

rule composite_tactic_aggregation {
  meta:
    rule_name = "MITRE Tactic Aggregation Composite"
    author = "Google Cloud Security"
    description = "Composite detection that detects if a user has triggered detections over multiple mitre tactics."
    severity = "Medium"

  events:
    $principal_user = $d.detection.detection.outcomes["principal_users"]
    $tactic = $d.detection.detection.rule_labels["tactic"]
    $rule_name = $d.detection.detection.rule_name

  match:
    $principal_user over 48h

  outcome:
    $mitre_tactics_count = count_distinct($tactic)
    $mitre_tactics = array_distinct($d.detection.rule_labels["tactic"])
    $risk_score = min(100, (50+15*$mitre_tactics_count))
    $upstream_rules = array_distinct($rule_name)

  condition:
    $d and $mitre_tactics_count > 1
}

連續複合偵測

連續複合式偵測會找出相關事件的模式,偵測順序非常重要,例如偵測到暴力登入嘗試,接著登入成功。這些模式可能涉及多個基本偵測結果,或基本偵測結果和事件的組合。

rule composite_bruteforce_login {
  meta:
    rule_name = "Bruteforce Login Composite"
    author = "Google Cloud Security"
    description = "Detects when an IP address associated with a Workspace brute force attempt successfully logs in"
    severity = "High"

  events:
    $bruteforce_detection.detection.detection.rule_name = /Workspace Anomalous Failed Logins/
    $bruteforce_ip = $d.detection.detection.outcomes["principal_ips"]

    $login_event.metadata.product_name = "login"
    $login_event.metadata.product_event_type = "login_success"
    $login_event.metadata.vendor_name = "Google Workspace"
    $login_ip = $login_event.principal.ip

    // Ensure the brute force detection and successful login occurred from the same IP
    $login_ip = $bruteforce_ip

    $target_account = $login_event.target.user.email_addresses

    // Ensure the brute force detection occurred before the successful login
    $bruteforce_detection.detection.detection_time.seconds < $login_event.metadata.event_timestamp.seconds

  match:
    $bruteforce_ip over 24h

  outcome:
    $risk_score = 90
    $principal_users = array_distinct($target_account)

  condition:
    $bruteforce_detection and $login_event
}

情境感知偵測

情境感知複合式偵測功能會提供額外情境資訊 (例如威脅動態消息中找到的 IP 位址),讓偵測結果更加豐富。

rule composite_tor_enrichment {
  meta:
    rule_name = "Detection with IP from TOR Feed"
    author = "Google Cloud Security"
    description = "Adds additional context from the TOR intel feed to detections"
    severity = "High"

  events:
    $detection_ip = $d.detection.detection.outcomes["principal_ips"]
    $gcti.graph.metadata.entity_type = "IP_ADDRESS"
    $gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence"
    $gcti_feed.graph.metadata.source_type = "GLOBAL_CONTEXT"
    $gcti.graph.metadata.product_name = "GCTI Feed"
    $gcti.graph.metadata.threat.threat_feed_name = "Tor Exit Nodes"

    $detection_ip = $gcti.graph.entity.ip

    $rule_name = $d.detection.detection.rule_name
    $risk = $d.detection.detection.outcomes["risk_score"]

  match:
    $detection_ip, $rule_name over 1h

  outcome:
    $risk_score = 80
    $upstream_rule = array_distinct($rule_name)

  condition:
    $d and $gcti
}

共同發生偵測

共同發生複合式偵測是一種匯總形式,可偵測相關事件的組合,例如使用者觸發的權限提升和資料外洩偵測組合。

rule composite_privesc_exfil_sequential {
  meta:
    rule_name = "Privilege Escalation and Exfiltration Composite"
    author = "Google Cloud Security"
    description = "Looks for a detection sequence of privilege escalation followed by exfiltration."
    severity = "High"

  events:
    $privilege_escalation.detection.detection.rule_labels["tactic"] = "TA0004"
    $exfiltration.detection.detection.rule_labels["tactic"] = "TA0010"

    $pe_user = $privilege_escalation.detection.detection.outcomes["principal_users"]
    $ex_user = $exfiltration.detection.detection.outcomes["principal_users"]

    $pe_user = $ex_user

  match:
    $pe_user over 48h

  outcome:
    $risk_score = 75
    $privesc_rules = array_distinct($privilege_escalation.detection.detection.rule_name)
    $exfil_rules = array_distinct($exfiltration.detection.detection.rule_name)

  condition:
    $privilege_escalation and $exfiltration
}

滑動視窗規則範例

以下 YARA-L 2.0 滑動視窗範例會搜尋 firewall_1 事件後沒有 firewall_2 事件的情況。after 關鍵字會與樞紐事件變數 $e1 搭配使用,指定在關聯事件時,只應檢查每個 firewall_1 事件後 10 分鐘內的時間範圍。

rule SlidingWindowRuleExample {
  meta:
    author = "alice@example.com"

  events:
    $e1.metadata.product_name = "firewall_1"
    $e1.principal.hostname = $host

    $e2.metadata.product_name = "firewall_2"
    $e2.principal.hostname = $host

  match:
    $host over 10m after $e1

  condition:
    $e1 and !$e2
}

排除零值範例

系統會隱含篩除「規則引擎」match部分中所有預留位置的零值。詳情請參閱match」部分中的零值處理方式。 如要停用這項功能,請使用 allow_zero_values 選項,詳情請參閱 allow_zero_values

不過,如果是其他參照的事件欄位,除非您明確指定這類條件,否則系統不會排除零值。

rule ExcludeZeroValues {
  meta:
    author = "alice@example.com"

  events:
    $e1.metadata.event_type = "NETWORK_DNS"
    $e1.principal.hostname = $hostname

    // $e1.principal.user.userid may be empty string.
    $e1.principal.user.userid != "Guest"

    $e2.metadata.event_type = "NETWORK_HTTP"
    $e2.principal.hostname = $hostname

    // $e2.target.asset_id cannot be empty string as explicitly specified.
    $e2.target.asset_id != ""

  match:
    // $hostname cannot be empty string. The rule behaves as if the
    // predicate, `$hostname != ""` was added to the events section, because
    // `$hostname` is used in the match section.
    $hostname over 1h

  condition:
    $e1 and $e2
}

含有 outcome 區段的規則範例

您可以在 YARA-L 2.0 規則中新增選用的 outcome 區段,擷取每次偵測的其他資訊。在條件部分,您也可以指定結果變數的條件。您可以使用偵測規則的 outcome 區段,設定供下游使用的變數。舉例來說,您可以根據所分析事件的資料設定嚴重程度分數。

如要瞭解詳情,請參考下列資源:

含有結果部分的複合事件規則:

下列規則會查看兩個事件,取得 $hostname 的值。如果 $hostname 的值在 5 分鐘內相符,系統就會套用嚴重程度分數。在 match 區段中加入時間範圍時,規則會檢查指定時間範圍內的資料。

rule OutcomeRuleMultiEvent {
    meta:
      author = "Google Cloud Security"
    events:
      $u.udm.principal.hostname = $hostname
      $asset_context.graph.entity.hostname = $hostname

      $severity = $asset_context.graph.entity.asset.vulnerabilities.severity

    match:
      $hostname over 5m

    outcome:
      $risk_score =
        max(
            100
          + if($hostname = "my-hostname", 100, 50)
          + if($severity = "HIGH", 10)
          + if($severity = "MEDIUM", 5)
          + if($severity = "LOW", 1)
        )

      $asset_id_list =
        array(
          if($u.principal.asset_id = "",
             "Empty asset id",
             $u.principal.asset_id
          )
        )

      $asset_id_distinct_list = array_distinct($u.principal.asset_id)

      $asset_id_count = count($u.principal.asset_id)

      $asset_id_distinct_count = count_distinct($u.principal.asset_id)

    condition:
      $u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}

rule OutcomeRuleMultiEvent {
    meta:
      author = "alice@example.com"
    events:
      $u.udm.principal.hostname = $hostname
      $asset_context.graph.entity.hostname = $hostname

      $severity = $asset_context.graph.entity.asset.vulnerabilities.severity

    match:
      $hostname over 5m

    outcome:
      $total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)

      $risk_score = if(total_network_bytes > 1024, 100, 50) + 
        max(
          if($severity = "HIGH", 10)
          + if($severity = "MEDIUM", 5)
          + if($severity = "LOW", 1)
        )

      $asset_id_list =
        array(
          if($u.principal.asset_id = "",
             "Empty asset id",
             $u.principal.asset_id
          )
        )

      $asset_id_distinct_list = array_distinct($u.principal.asset_id)

      $asset_id_count = count($u.principal.asset_id)

      $asset_id_distinct_count = count_distinct($u.principal.asset_id)

    condition:
      $u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}

含有結果部分的單一事件規則:

rule OutcomeRuleSingleEvent {
    meta:
        author = "alice@example.com"
    events:
        $u.metadata.event_type = "FILE_COPY"
        $u.principal.file.size = $file_size
        $u.principal.hostname = $hostname

    outcome:
        $suspicious_host = $hostname
        $admin_severity = if($u.principal.userid in %admin_users, "SEVERE", "MODERATE")
        $severity_tag = if($file_size > 1024, $admin_severity, "LOW")

    condition:
        $u
}

將多重事件結果規則重構為單一事件結果規則。

您可以將outcome部分用於單一事件規則 (不含 match 部分的規則) 和多重事件規則 (含 match 部分的規則)。如果您先前設計的規則是多事件規則,只是為了使用結果部分,可以選擇刪除 match 部分來重構這些規則,以提升成效。請注意,由於規則不再有適用於分組的 match 區段,您可能會收到更多偵測結果。只有使用一個事件變數的規則才能進行這項重構,如下列範例所示。

多事件結果規則,只使用一個事件變數 (很適合重構):

rule OutcomeMultiEventPreRefactor {
    meta:
      author = "alice@example.com"
      description = "Outcome refactor rule, before the refactor"

    events:
      $u.udm.principal.hostname = $hostname

    match:
      $hostname over 5m

    outcome:
      $risk_score = max(if($hostname = "my-hostname", 100, 50))

    condition:
      $u
}

您可以刪除 match 區段,重構規則。請注意,由於規則現在是單一事件,您也必須移除「outcome」部分中的匯總。如要進一步瞭解匯總,請參閱結果匯總

rule OutcomeSingleEventPostRefactor {
    meta:
      author = "alice@example.com"
      description = "Outcome refactor rule, after the refactor"

    events:
      $u.udm.principal.hostname = $hostname

    // We deleted the match section.

    outcome:
      // We removed the max() aggregate.
      $risk_score = if($hostname = "my-hostname", 100, 50)

    condition:
      $u
}

函式至預留位置規則範例

您可以將預留位置變數指派給函式呼叫的結果,並在規則的其他部分使用預留位置變數,例如 match 區段、outcome 區段或 condition 區段。請參閱以下範例:

rule FunctionToPlaceholderRule {
    meta:
      author = "alice@example.com"
      description = "Rule that uses function to placeholder assignments"

    events:
        $u.metadata.event_type = "EMAIL_TRANSACTION"

        // Use function-placeholder assignment to extract the
        // address from an email.
        // address@website.com -> address
        $email_to_address_only = re.capture($u.network.email.from , "(.*)@")

        // Use function-placeholder assignment to normalize an email:
        // uid@??? -> uid@company.com
        $email_from_normalized = strings.concat(
            re.capture($u.network.email.from , "(.*)@"),
            "@company.com"
        )

        // Use function-placeholder assignment to get the day of the week of the event.
        // 1 = Sunday, 7 = Saturday.
        $dayofweek = timestamp.get_day_of_week($u.metadata.event_timestamp.seconds)

    match:
        // Use placeholder (from function-placeholder assignment) in match section.
        // Group by the normalized from email, and expose it in the detection.
        $email_from_normalized over 5m

    outcome:
        // Use placeholder (from function-placeholder assignment) in outcome section.
        // Assign more risk if the event happened on weekend.
        $risk_score = max(
            if($dayofweek = 1, 10, 0) +
            if($dayofweek = 7, 10, 0)
        )

    condition:
        // Use placeholder (from function-placeholder assignment) in condition section.
        // Match if an email was sent to multiple addresses.
        #email_to_address_only > 1
}

結果條件式範例規則

condition 區段中,您可以使用 outcome 區段中定義的結果變數。以下範例說明如何使用結果條件式,依風險分數進行篩選,減少偵測結果中的干擾。

rule OutcomeConditionalRule {
    meta:
        author = "alice@example.com"
        description = "Rule that uses outcome conditionals"

    events:
        $u.metadata.event_type = "FILE_COPY"
        $u.principal.file.size = $file_size
        $u.principal.hostname = $hostname

        // 1 = Sunday, 7 = Saturday.
        $dayofweek = timestamp.get_day_of_week($u.metadata.collected_timestamp.seconds)

    outcome:
        $risk_score =
            if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
            if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
            if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
            if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices

    condition:
        $u and $risk_score >= 10
}

還有其他問題嗎?向社群成員和 Google SecOps 專業人員尋求答案。