結果區段語法

支援的服務:

YARA-L 查詢的 outcome 區段會定義結果變數,指定搜尋和資訊主頁查詢的輸出內容,以及規則觸發時偵測到的其他背景資訊和資訊。這些變數可用於多種用途,例如在資訊主頁上顯示相關資料,以及建立風險評分。

定義結果部分

在單一查詢的 outcome 部分,使用 $ 字元,後面加上變數名稱,即可定義結果變數。您最多可以定義 20 個結果變數。變數名稱本身可任意設定。如果是規則,系統會根據每次偵測計算並匯總結果值。

每個結果變數都會使用運算式指派值。

這項規則會搜尋從新位置登入失敗的記錄:

rule failed_logins
{
  meta:
   author = "Security Team"
   description = "Detects multiple failed user logins within 10-minute windows."
   severity = "HIGH"

  events:
   $e.metadata.event_type = "USER_LOGIN"
   $e.security_result.action = "FAIL"
   $user = $e.target.user.userid

  match:
   $user over 10m

  outcome:
   $failed_login_count = count($e.metadata.id)
   $first_fail_time = min($e.metadata.event_timestamp.seconds)

  condition:
   #e >= 5
}

outcome 區段會對事件和預留位置變數執行匯總:計算失敗的登入次數、計算不重複 IP,以及取得失敗發生的時間。

outcome:
   $failed_login_count = count($e.metadata.id)
   $first_fail_time = min($e.metadata.event_timestamp.seconds)

如果您加入並填入特殊 $risk_score 結果變數,其值 (整數或浮點數) 會顯示在「Alerts and IoCs」(快訊和 IoC) 頁面,用於查詢產生的快訊。

如果您未在查詢的 outcome 區段中加入 $risk_score 變數,系統會設定下列其中一個預設值:

  • 如果查詢設為產生警告,$risk_score 會設為 40。

  • 如果查詢未設為產生警告,$risk_score 會設為 15。

$risk_score 的值會儲存在 security_result.risk_score UDM 欄位中。

risk_score 結果變數

Google SecOps 風險分析會自動將偵測結果和警示,與相關實體建立關聯。risk_score 結果變數用於指派風險量。如未設定這個值,系統會使用預設偵測或警告值。您可以在「設定」中設定預設值。

為確保整個平台的一致性,建議您在為自訂偵測項目指派 risk_score 時,使用下列分數範圍。這項對應有助於標準化警示優先順序和應變工作流程。

嚴重程度 分數範圍 說明 範例
警告 - 重大 90 - 100 主動入侵,可能影響多個使用者帳戶或端點。需要立即審查。 在網域控制站上執行 Mimikatz。
警告 - 高 80 - 89 單一端點或實體遭到入侵。應立即審查。 正式環境伺服器呼叫最近已知的 C2。
警告 - 中 50 - 79 潛在安全性問題,需要調查。未確認是否遭入侵,但有可能升級。 憑證外洩,但沒有濫用跡象。
非警示 - 低 20 - 49 影響較小的安全性事件,但如果與其他指標或觀察結果結合,可能會導致更重大的事件。通常不需要審查,可透過複合規則與其他偵測項目合併,建立快訊。 內部通訊埠掃描。
非警告觀察項目 1 - 19 一般來說,這類偵測功能會根據資訊,建立威脅情境感知。通常不需要審查,可透過複合規則與其他偵測項目合併,產生快訊。 登入事件,沒有濫用跡象。

由於 risk_score 是結果變數,因此規則可以根據威脅情報或其他並行條件等因素,表達細微差異。

實體風險評分可用於近乎即時地產生風險快訊。詳情請參閱「風險分析總覽」。

risk_entity_to_score 結果變數

根據預設,Google SecOps 會將偵測到的風險分數指派給取樣事件中的所有實體。並將分數指派給規則 match 和 outcome 區段中擷取的所有實體。如要將風險分數指派給特定實體,請一併指定 risk_entity_to_score 結果變數和 risk_score。風險評分支援 user 和 asset 實體。不支援 RESOURCE 或 GROUP 實體類型。

您可以建立多個 risk_entity_to_score 變數,方法是在變數中附加不重複的字串,並將風險評分指派給特定實體。例如:

$risk_entity_to_score_source_asset = $e.principal.asset.hostname
$risk_entity_to_score_targeted_user = $e.target.user.userid

這些結果變數會將規則 outcome 部分中指定的 risk_score 指派給 $e.principal.asset.hostname 和 $e.target.user.userid 實體。

範例:偵測管理員帳戶登入活動的規則

這項規則會偵測高權限管理員帳戶的成功登入事件。它會使用 risk_entity_to_score 關鍵字,明確指定已登入的特定使用者。使用這個變數,偵測功能可確保計算出的風險評分僅適用於該使用者,而不適用於事件中涉及的其他實體,例如來源 IP 位址。

如要進一步瞭解如何編寫多事件規則,請參閱「多事件規則」。

rule suspicious_admin_privilege_escalation {
 // This rule matches single events. Rules can also match multiple events within
 // the same time window.

 meta:
   // Allows for storage of arbitrary key-value pairs of rule details, such as 
   // who wrote it, what it detects on, and version control.
   // The "author" and "severity" fields are special, since they are used as
   // columns on the rules dashboard. To sort based on these fields on the 
   // dashboard, add them here.
   // Severity value should be "Low", "Medium", or "High"
   author = "analyst123"
   description = "Detects suspicious login to critical admin accounts."
   severity = "HIGH"

 events:
   $e.metadata.event_type = "USER_LOGIN"
   $e.target.user.attribute.roles.name = "ADMIN"
   $e.security_result.summary = "Successful login with high-privilege access"

 outcome:
   // Multi-event rules require an aggregation function
   // For example, risk_score = max(0)
   // See https://docs.cloud.google.com/chronicle/docs/yara-l/yara-l-2-0-examples#outcome_conditionals_example_rule
   $risk_score = 80
   $risk_entity_to_score = $e.target.user.userid
   $source_ip = array_distinct($e.principal.ip)

 condition:
   $e
}

範例:規則會監控內部網路連線

這項規則會找出內部網路區隔之間的網路連線,檢查是否有橫向移動。它會使用 $risk_entity_to_score prefix,在單一偵測中為多個實體指派風險。發起主機 ($risk_entity_to_score_source_asset) 和目標使用者 ($risk_entity_to_score_targeted_user) 的風險評分都會更新。風險引擎會記錄其他不使用這個特定前置字串的結果變數,但會忽略這些變數 (其風險分數維持不變)。

如要進一步瞭解如何編寫多事件規則,請參閱「多事件規則」和「結果條件範例規則」。

rule lateral_movement_network_connection {
 // This rule matches single events. You can also match multiple events within
 // the same time window.

 meta:
   // Allows for storage of arbitrary key-value pairs of rule details (for 
   // example, who wrote it, what it detects on, and version control).
   // The "author" and "severity" fields are special, since they are used as
   // columns on the rules dashboard. To sort based on these fields on the 
   // dashboard, add them here. Severity value should be "Low", "Medium" or "High"
   author = "analyst123"
   description = "Detects lateral movement attempts between internal segments."
   severity = "MEDIUM"

 events:
   $e.metadata.event_type = "NETWORK_CONNECTION"
   $e.principal.asset.hostname != ""
   $e.target.user.userid != ""
   // Can also use: $e.target.ip = /10\..*/
   net.ip_in_range_cidr($e.target.ip, "10.0.0.0/8")

 outcome:
   // Multi-event rules require an aggregation function
   // for example, risk_score = max(0)
   // See https://docs.cloud.google.com/chronicle/docs/yara-l/yara-l-2-0-examples#outcome-conditionals-example-rule
   $risk_score = 50
   $risk_entity_to_score_source_asset = $e.principal.asset.hostname
   $risk_entity_to_score_targeted_user = $e.target.user.userid
   $target_ip_info = array_distinct($e.target.ip)

 condition:
   $e
}

結果變數資料類型

每個結果變數都可以有不同的資料類型,具體取決於用來計算該變數的運算式。Google SecOps 支援下列結果資料類型:

  • 整數
  • floats
  • 字串
  • 整數清單
  • 浮點數清單
  • 字串清單

條件式邏輯

您可以使用條件邏輯來計算結果的值。條件式會使用下列語法模式指定:

if(BOOL_CLAUSE, THEN_CLAUSE)
if(BOOL_CLAUSE, THEN_CLAUSE, ELSE_CLAUSE)

條件運算式可以解讀為「如果 BOOL_CLAUSE 為 true,則傳回 THEN_CLAUSE,否則傳回 ELSE_CLAUSE」。

BOOL_CLAUSE 的評估結果必須是布林值。BOOL_CLAUSE 運算式的形式與 events 區段中的運算式類似。例如:

  • UDM 欄位名稱和比較運算子:

    if($context.graph.entity.user.title = "Vendor", 100, 0)

  • 在 events 區段中定義的預留位置變數:

    if($severity = "HIGH", 100, 0)

  • outcome 區段中定義的另一個結果變數:

    if($risk_score > 20, "HIGH", "LOW")

  • 傳回布林值的函式:

    if(re.regex($e.network.email.from, `.*altostrat.com`), 100, 0)

  • 在參照清單中查詢:

    if($u.principal.hostname in %my_reference_list_name, 100, 0)

  • 匯總比較:

    if(count($login.metadata.event_timestamp.seconds) > 5, 100, 0)

THEN_CLAUSE 和 ELSE_CLAUSE 必須是相同的資料類型。我們支援整數、浮點數和字串。

如果資料類型是整數或浮點數,則可省略 ELSE_CLAUSE。如果省略,ELSE_CLAUSE 的評估結果會是 0。例如:

`if($e.field = "a", 5)` is equivalent to `if($e.field = "a", 5, 0)`

如果資料類型為字串,或 THEN_CLAUSE 是預留位置變數或結果變數,則必須提供 ELSE_CLAUSE。

數學運算

您可以使用數學運算,在查詢的 outcome 和 events 部分計算整數或浮點資料類型。Google Security Operations 支援加、減、乘、除和模數,做為運算中的頂層運算子。

以下程式碼片段是 outcome 區段中的運算範例:

outcome:
  $risk_score = max(100 + if($severity = "HIGH", 10, 5) - if($severity = "LOW", 20, 0))

只要每個運算元和整個算術運算式都經過適當匯總,下列類型的運算元就可進行數學運算 (請參閱「匯總」):

  • 數值事件欄位
  • 在 events 區段中定義的數字預留位置變數
  • 在 outcome 區段中定義的數值結果變數
  • 傳回整數或浮點數的函式
  • 傳回整數或浮點數的匯總

浮點數不允許使用模數。

標準整數常值預設為有正負號的 64 位元整數 (INT64),與無正負號的 64 位元整數 (UINT64) UDM 欄位不相容,例如 network.received_bytes、network.sent_bytes 和 principal.file.size。在算術 (+、-、*) 或模數 (%) 運算中合併這些類型,可能會導致 outcome 區段發生執行階段錯誤。如要解決這個問題,請使用 cast.as_int() 或 cast.as_uint() 比對整數類型。% 運算子必須明確轉換。對於算術運算,您也可以使用浮點常值 (例如 2.0 或 100.0) 或除法強制轉型 (例如 (2/1)),在同一行沒有其他 / 運算子的運算式中,強制整數常數做為浮點數。詳情請參閱「使用無正負號事件欄位進行算術運算」。

結果中的預留位置變數

計算結果變數時,您可以使用在查詢的事件區段中定義的預留位置變數。在這個範例中,假設 $email_sent_bytes 是在規則的事件部分中定義:

範例:單一事件,沒有不相符部分

// No match section, so this is a single-event query.

outcome:
  // Use placeholder directly as an outcome value.
  $my_outcome = $email_sent_bytes

  // Use placeholder in a conditional.
  $other_outcome = if($file_size > 1024, "SEVERE", "MODERATE")

condition:
  $e

範例:包含比對區段的多重事件

match:
  // This is a multi event query with a match section.
  $hostname over 5m

outcome:
  // Use placeholder directly in an aggregation function.
  $max_email_size = max($email_sent_bytes)

  // Use placeholder in a mathematical computation.
  $total_bytes_exfiltrated = sum(
    1024.0
    + $email_sent_bytes
    + $file_event.principal.file.size
  )

condition:
  $email_event and $file_event

結果指派運算式中的結果變數

結果變數可用於衍生其他結果變數,類似於 events 區段中定義的預留位置變數。您可以在指派另一個結果變數時,使用 $ 符號加上變數名稱,參照結果變數。必須先定義結果變數,才能在查詢文字中參照。在指派運算式中使用時,結果變數不得匯總 (請參閱「匯總」)。

在以下範例中,結果變數 $risk_score 的值衍生自結果變數 $event_count:

範例:從另一個結果變數衍生的結果變數

match:
  // This is a multi event query with a match section.
  $hostname over 5m

outcome:
  // Aggregates all timestamp on login events in the 5 minute match window.
  $event_count = count($login.metadata.event_timestamp.seconds)

  // $event_count cannot be aggregated again.
  $risk_score = if($event_count > 5, "SEVERE", "MODERATE")

  // This is the equivalent of the 2 outcomes combined.
  $risk_score2 = if(count($login.metadata.event_timestamp.seconds) > 5, "SEVERE", "MODERATE")

condition:
  $e

結果變數可用於結果指派右側的任何運算式類型,但下列運算式除外:

  • 匯總資料
  • Arrays.length() 次函式呼叫
  • 使用 any 或 all 修飾符

匯總資料

重複的事件欄位是非純量值。也就是說,單一變數會指向多個值。舉例來說,事件欄位變數 $e.target.ip 是重複欄位,可以有零、一或多個 IP 值。這不是純量值。而事件欄位變數 $e.principal.hostname 不是重複欄位,且只有 1 個值 (即純量值)。

同樣地,在具有比對時間範圍的查詢中,outcome 區段使用的非重複事件欄位和重複事件欄位都是非純量值。

範例:含有比對區段和非重複欄位的群組事件

下列查詢會使用「match」區段將事件分組,並參照「outcome」區段中的非重複事件欄位:

rule OutcomeAndMatchWindow{
  ...
  match:
    $userid over 5m
  outcome:
    $hostnames = array($e.principal.hostname)
  ...
}

查詢執行的任何 5 分鐘時間範圍內,可能包含零、一或多個事件。結果部分會對比對視窗中的所有事件執行。結果區段中參照的任何事件欄位變數,都可以指向比對期間內每個事件欄位的零、一或多個值。舉例來說,如果 5 分鐘的時間範圍內包含 5 個 $e 事件,結果部分的 $e.principal.hostname 會指向五個不同的主機名稱。在這項查詢的 outcome 部分,事件欄位變數 $e.principal.hostname 會視為非純量值。

由於結果變數一律必須產生單一純量值,因此結果指派作業所依據的任何非純量值,都必須匯總產生單一純量值。在結果部分,下列是非純量值,必須匯總:

  • 查詢使用 match 區段時的事件欄位 (重複或非重複)
  • 查詢使用 match 區段時,事件預留位置 (重複或不重複)
  • 查詢未使用 match 區段時,重複的事件欄位
  • 查詢未使用 match 區段時,重複活動預留位置

在不含 match 區段的查詢中,純量事件欄位、純量事件預留位置和常數可以包裝在匯總函式中。不過,在大多數情況下,這些匯總會傳回包裝值,因此不必要。array() 匯總函式是例外狀況,可用來將純量值明確轉換為陣列。

結果變數會視為匯總:在其他結果指派中參照時,不得重新匯總。

您可以使用下列匯總函式:

匯總函式 說明
max() 輸出所有可能值的最大值。僅適用於整數和浮點數。
min() 輸出所有可能值的最小值。僅適用於整數和浮點數。
sum() 輸出所有可能值的總和。僅適用於整數和浮點數。
count_distinct() 收集所有可能的值,然後輸出可能值的不重複計數。
count() 運作方式與 `count_distinct()` 類似,但會傳回可能值的非不重複計數。
array_distinct() 收集所有可能的不重複值,然後輸出這些值的清單。系統會先簡化資料,產生不重複的清單,然後再截斷資料。在 Google 搜尋中,清單最多會截斷為 1,000 個隨機元素。在資訊主頁和規則中,清單最多會截斷為 25 個隨機元素。
array() 行為與 array_distinct() 類似,但會傳回非相異值清單。在搜尋中,清單最多會截斷為 1,000 個隨機元素。在資訊主頁和規則中,清單最多會截斷為 25 個隨機元素。

如果規則包含 condition 區段,指定必須存在多個事件,則匯總函式很重要,因為匯總函式會對產生偵測的所有事件執行。

範例:多個事件的條件

以下是多個事件的條件範例。如果結果和條件部分包含:

outcome:
  $asset_id_count = count($event.principal.asset_id)
  $asset_id_distinct_count = count_distinct($event.principal.asset_id)

  $asset_id_list = array($event.principal.asset_id)
  $asset_id_distinct_list = array_distinct($event.principal.asset_id)

condition:
  #event > 1

由於「condition」部分要求每次偵測必須有多個「event」,因此匯總函式會對多個事件執行。假設下列事件產生一項偵測結果:

event:
  // UDM event 1
  asset_id="asset-a"

event:
  // UDM event 2
  asset_id="asset-b"

event:
  // UDM event 3
  asset_id="asset-b"

則結果值會是:

    $asset_id_count = 3
    $asset_id_distinct_count = 2
    $asset_id_list = `["asset-a", "asset-b", "asset-b"]
    $asset_id_distinct_list = `["asset-a", "asset-b"]

限制

  • outcome 區段無法參照未在 events 區段或 outcome 區段中定義的新預留位置變數。

  • outcome 區段無法使用未在 events 區段中定義的事件變數。

  • outcome 區段可以使用未在 events 區段中使用的事件欄位,前提是事件欄位所屬的事件變數已在 events 區段中定義。

  • outcome 區段只能關聯已在 events 區段中關聯的事件變數。當不同事件變數中的兩個事件欄位相等時,就會發生關聯。

如需 outcome 區段的範例,請參閱「YARA-L 2.0 總覽」。

如要瞭解如何使用 outcome 區段刪除重複偵測項目,請參閱「建立內容感知分析」。

後續步驟

其他資訊

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