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 專業人員尋求答案。