重複欄位

支援的國家/地區:

在整合式資料模型 (UDM) 中,部分欄位標示為重複,表示這些欄位是值清單或其他類型的訊息。本文說明如何針對重複的 UDM 欄位使用運算式、預留位置、陣列索引和重複訊息。

布林運算式和重複欄位

修改過和未修改的布林運算式都可以作用於重複欄位。

請參考下列事件:

event_original {
  principal {
    // ip is a repeated field
    ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]

    hostname: "host"
  }
}

已修改的運算式

在重複欄位的運算式中使用 anyall 修飾符。

  • any - 如果重複欄位的任何元素符合條件,則整個事件都符合條件。例如:

    • event_original 滿足 any $e.principal.ip = "192.0.2.1"
    • event_original失敗any $e.repeated_field.field_a = "9.9.9.9"
  • all - 如果重複欄位的所有元素都符合條件,則事件整體符合條件。例如:

    • event_original 滿足 net.ip_in_range_cidr(all $e.principal.ip, "192.0.2.0/8")
    • event_original失敗all $e.principal.ip = "192.0.2.2"

使用 anyall 撰寫條件時,請注意以 not 否定條件,可能與使用否定運算子意義不同。

例如:

  • not all $e.principal.ip = "192.168.12.16" 會檢查是否所有 IP 位址都符合 192.168.12.16,也就是說,查詢會檢查至少一個 IP 位址是否不符合 192.168.12.16
  • all $e.principal.ip != "192.168.12.16" 會檢查所有 IP 位址是否都不符合 192.168.12.16,也就是查詢是否沒有任何 IP 位址符合 192.168.12.16

限制:

  • anyall 運算子僅適用於重複欄位 (不適用於純量欄位)。
  • anyall 無法用於聯結兩個重複欄位。舉例來說,any $e1.principal.ip = $e2.principal.ip 是無效。
  • 參考清單運算式不支援 anyall 運算子。

未修改的運算式

如果運算式未經修改,系統會個別處理重複欄位中的每個元素。如果事件的重複欄位包含 n 個元素,查詢會套用至事件的 n 個副本,每個副本都有重複欄位中的其中一個元素。這些副本是暫時性的,不會儲存。

這項規則會套用至下列副本:

活動副本 principal.ip principal.hostname
event_copy_1 「192.0.2.1」 「host」
event_copy_2 「192.0.2.2」 「host」
event_copy_3 「192.0.2.3」 「host」

如果任何事件副本符合重複欄位中的所有未修改條件,則該事件整體符合所有條件。因此,如果重複欄位有多個條件,單一事件副本必須滿足「所有」條件。下列查詢範例會使用上述範例資料集,示範這項行為。

示例:未修改的運算式

針對 event_original 範例資料集執行下列規則時,會傳回一個相符項目,因為 event_copy_1 符合所有事件述詞:

rule repeated_field_1 {
  meta:
  events:
    net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/8") // Checks if IP address matches 192.x.x.x
    $e.principal.ip = "192.0.2.1"
  condition:
    $e
}

針對 event_original 範例資料集執行下列規則時,不會傳回相符項目,因為 $e.principal.ip 中沒有符合「所有」事件述詞的事件副本。

rule repeated_field_2 {
  meta:
  events:
    $e.principal.ip = "192.0.2.1"
    $e.principal.ip = "192.0.2.2"
  condition:
    $e
}

重複欄位上的修改運算式與重複欄位上的未修改運算式相容,因為每個事件副本的元素清單都相同。請參考以下規則:

rule repeated_field_3 {
  meta:
  events:
    any $e.principal.ip = "192.0.2.1"
    $e.principal.ip = "192.0.2.3"
  condition:
    $e
}

這項規則會套用至下列副本:

活動副本 principal.ip any $e.principal.ip
event_copy_1 「192.0.2.1」 ["192.0.2.1", "192.0.2.2", "192.0.2.3"]
event_copy_2 「192.0.2.2」 ["192.0.2.1", "192.0.2.2", "192.0.2.3"]
event_copy_3 「192.0.2.3」 ["192.0.2.1", "192.0.2.2", "192.0.2.3"]

在本例中,所有副本都符合 any $e.principal.ip = "192.0.2.1",但只有 event_copy_3 符合 $e.principal.ip = "192.0.2.3"。因此,整個活動都會相符。

這些運算式類型也可以這樣理解:

  • 使用 anyall 的重複欄位運算式會在 event_original 的清單中運作。
  • 重複欄位上的運算式 (不使用 anyall) 會對個別 event_copy_n 事件執行運算。

預留位置和重複欄位

重複欄位可搭配預留位置指派作業使用。與重複欄位中未修改的運算式類似,系統會為每個元素建立事件副本。以 event_copy 為例,預留位置會取得 event_copy_n 的重複欄位值,其中 n 是事件副本編號。如果預留位置用於比對區段,可能會導致多個相符項目。

範例:重複欄位預留位置

以下範例會產生一個相符項目。`$ip` 預留位置等於 `event_copy_1` 的 `192.0.2.1`,符合規則中的述詞。相符項的事件樣本包含單一元素 `event_original`。

// Generates 1 match.
rule repeated_field_placeholder1 {
  meta:
  events:
    $ip = $e.principal.ip
    $ip = "192.0.2.1"
    $host = $e.principal.hostname

  match:
    $host over 5m

  condition:
    $e
}

以下範例會產生三筆相符項目。$ip 預留位置等於不同值,適用於每個不同的 event_copy_n 副本。分組程序是按照 $ip 執行,因為該項目位於比對區段。因此,您會得到三場比賽,每場比賽的 $ip 比賽變數值都不同。每個相符項目都有相同的事件樣本:單一元素 event_original

// Generates 3 matches.
rule repeated_field_placeholder2 {
  meta:
  events:
    $ip = $e.principal.ip
    net.ip_in_range_cidr($ip, "192.0.2.0/8") // Checks if IP matches 192.x.x.x

  match:
    $ip over 5m

  condition:
    $e
}

指派給重複欄位的預留位置所產生的結果

系統會為每個重複欄位的每個元素指派預留位置,而非整個清單。在 outcome 區段中使用時,系統只會使用滿足先前區段的元素計算結果。

請參考以下規則:

rule outcome_repeated_field_placeholder {
  meta:
  events:
    $ip = $e.principal.ip
    $ip = "192.0.2.1" or $ip = "192.0.2.2"
    $host = $e.principal.hostname

  match:
    $host over 5m

  outcome:
    $o = array_distinct($ip)

  condition:
    $e
}

這項規則的執行作業分為四個階段。第一階段是複製活動:

活動副本 $ip $host $e
event_copy_1 「192.0.2.1」 「host」 event_id
event_copy_2 「192.0.2.2」 「host」 event_id
event_copy_3 「192.0.2.3」 「host」 event_id

事件區段隨即會篩除不符合篩選條件的資料列:

活動副本 $ip $host $e
event_copy_1 「192.0.2.1」 「host」 event_id
event_copy_2 「192.0.2.2」 「host」 event_id

event_copy_3 已遭濾除,因為 "192.0.2.3" 不符合 $ip = "192.0.2.1" or $ip = "192.0.2.2"

接著,match 區段會依比對變數分組,而 outcome 區段則會對每個群組執行匯總:

$host $o $e
「host」 ["192.0.2.1", "192.0.2.2"] event_id

$o = array_distinct($ip) 是使用前一個階段的 $ip 計算得出,而非事件複製階段。

最後,condition 區段會篩選每個群組。由於這項規則只會檢查 $e 是否存在,因此先前資料列會產生單一偵測結果。

$o 並未包含 $e.principal.ip 中的所有元素,因為並非所有元素都符合事件部分的所有條件。不過,由於事件範例使用 event_original,因此 e.principal.ip 的所有元素都會顯示在事件範例中。

陣列索引

您可以對重複欄位執行陣列索引。如要存取第 n 個重複欄位元素,請使用標準清單語法 (元素以 0 為索引)。超出界限的元素會傳回預設值。

  • $e.principal.ip[0] = "192.168.12.16"
  • $e.principal.ip[999] = "" 如果元素少於 1000 個,則評估結果為 true

限制:

  • 索引必須是非負整數常值。舉例來說,$e.principal.ip[-1] 是無效。
  • 如果值為 int 類型 (例如設為 int 的預留位置),則不計入。
  • 陣列索引無法與 anyall 合併使用。舉例來說,any $e.intermediary.ip[0] 是無效。
  • 陣列索引無法與對應語法合併使用。舉例來說,$e.additional.fields[0]["key"] 是無效。
  • 如果欄位路徑包含多個重複欄位,所有重複欄位都必須使用陣列索引。舉例來說,$e.intermediary.ip[0] 無效,因為 intermediaryip 都是重複欄位,但只有 ip 有索引。

重複訊息

重複 message 欄位會產生非預期的效果,降低比對成功的機率。如以下範例所示。

請參考下列事件:

event_repeated_message {
  // about is a repeated message field.
  about {
    // ip is a repeated string field.
    ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]

    hostname: "alice"
  }
  about {
    hostname: "bob"
  }
}

如重複欄位中未修改的運算式所述,系統會為重複欄位的每個元素建立事件的暫時副本。請參考以下規則:

rule repeated_message_1 {
  meta:
  events:
    $e.about.ip = "192.0.2.1"
    $e.about.hostname = "bob"
  condition:
    $e
}

這項規則會套用至下列副本:

活動副本 about.ip about.hostname
event_copy_1 「192.0.2.1」 「alice」
event_copy_2 「192.0.2.2」 「alice」
event_copy_3 「192.0.2.3」 「alice」
event_copy_4 "" "bob"

由於沒有任何事件副本符合所有運算式,因此事件不符合規則。

重複訊息和陣列索引

如果對重複訊息欄位使用陣列索引,且未修改運算式,也可能發生非預期的行為。請參考下列使用陣列索引的規則範例:

rule repeated_message_2 {
  meta:
  events:
    $e.about.ip = "192.0.2.1"
    $e.about[1].hostname = "bob"
  condition:
    $e
}

這項規則會套用至下列副本:

活動副本 about.ip about[1].hostname
event_copy_1 「192.0.2.1」 "bob"
event_copy_2 「192.0.2.2」 "bob"
event_copy_3 「192.0.2.3」 "bob"
event_copy_4 "" "bob"

由於 event_copy_1 滿足 repeated_message_2 中的所有運算式,因此事件符合規則。

這可能會導致非預期的行為,因為規則 repeated_message_1 缺少陣列索引,因此沒有產生任何相符項目,而規則 repeated_message_2 使用陣列索引,因此產生相符項目。

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