運算式、運算子和其他建構體

支援的國家/地區:

本文提供相關資訊,協助您使用運算式建構 YARA-L 規則和查詢。

布林運算式

布林運算式是布林型別的運算式,包括比較運算式、函式運算式,以及參照清單或資料表運算式。您可以在 YARA-L 規則或查詢的 eventsoutcome 區段中使用布林運算式。

比較運算式

比較運算式是指對兩個運算式套用比較運算子的運算式。運算式可以是事件欄位、變數、常值或函式運算式。

範例:比較運算式

$e.source.hostname = "host1234"
$e.source.port < 1024
1024 < $e.source.port
$e1.source.hostname != $e2.target.hostname
$e1.metadata.collected_timestamp.seconds > $e2.metadata.collected_timestamp.seconds
$port >= 25
$host = $e2.target.hostname
"google-test" = strings.concat($e.principal.hostname, "-test")
"email@google.org" = re.replace($e.network.email.from, "com", "org")

函式運算式

部分函式運算式會傳回布林值,可用做 events 區段中的個別述詞,例如:

re.regex()

net.ip_in_range_cidr()

範例:函式運算式

re.regex($e.principal.hostname, `.*\.google\.com`)
net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")

參考清單或資料表

您可以在 eventsoutcome 區段中使用參照清單或資料表。如要進一步瞭解參照清單和資料表的行為與語法,請參閱「參照清單」和「使用資料表」。

範例:參考清單的語法

下列範例顯示查詢中各種參照清單的語法:

// STRING reference list
$e.principal.hostname in %string_reference_list

// REGEX reference list
$e.principal.hostname in regex %regex_reference_list

// CIDR reference list
$e.principal.ip in cidr %cidr_reference_list

範例:資料表的語法

// STRING data table
$e.target.hostname in %data_table_name.column_name

// REGEX data table
$e.target.hostname in regex %regex_table_name.column_name

// CIDR data table
$e.principal.ip in cidr %cidr_table_name.column_name

範例:在參照清單語法中使用 notnocase

// Exclude events whose hostnames match substrings in my_regex_list.
not $e.principal.hostname in regex %my_regex_list

// Event hostnames must match at least 1 string in my_string_list (case insensitive).
$e.principal.hostname in %my_string_list nocase

nocase 運算子與 STRING 清單和 REGEX 清單相容。

基於效能考量,參考清單和資料表的使用有以下限制:

  • 查詢中的 in 陳述式數量上限 (無論是否使用特殊運算子):7
  • 使用 regex 運算子的 in 陳述式數量上限:4
  • 使用 cidr 運算子的 in 陳述式數量上限:2

邏輯運算式

您可以在「events」部分使用邏輯 andor 運算子。

範例:邏輯運算式

$e.metadata.event_type = "NETWORK_DNS" or $e.metadata.event_type = "NETWORK_DHCP"
($e.metadata.event_type = "NETWORK_DNS" and $e.principal.ip = "192.0.2.12") or ($e.metadata.event_type = "NETWORK_DHCP" and $e.principal.mac = "AB:CD:01:10:EF:22")
not $e.metadata.event_type = "NETWORK_DNS"

根據預設,優先順序從高到低依序為 notandor。舉例來說,如果運算式中明確定義了 orand 運算子,「a or b and c」會評估為「a or (b and c)」。

events 區段中,如果未明確定義運算子,系統會使用 and 運算子聯結述詞。如果運算式中隱含 and 運算子,評估順序可能會有所不同。 請參考下列比較運算式,其中 or 是明確定義,而 and 運算子是隱含。

$e1.field = "bat"
or $e1.field = "baz" 
$e2.field = "bar"

解讀方式如下:

($e1.field = "bat" or $e1.field = "baz")
and ($e2.field = "bar")

由於 or 是明確定義的,因此系統會先將周圍的述詞分組並評估。最後一個述語 $e2.field = "bar"。是使用 and 隱含加入。因此評估順序會有所變更。

列舉型別

您可以在列舉型別中使用運算子。這項功能可套用至規則,簡化及最佳化成效 (使用運算子而非參照清單)。

在下列範例中,「USER_UNCATEGORIZED」和「USER_RESOURCE_DELETION」分別對應 15000 和 15014,因此規則會尋找所有列出的事件:

$e.metadata.event_type >= "USER_CATEGORIZED" and $e.metadata.event_type <= "USER_RESOURCE_DELETION"

Nocase 修飾符

如要在字串值或規則運算式之間的比較運算式中忽略大寫,請在運算式結尾附加 nocase,如下列範例所示。

範例:nocase 修飾符

$e.principal.hostname != "http-server" nocase
$e1.principal.hostname = $e2.target.hostname nocase
$e.principal.hostname = /dns-server-[0-9]+/ nocase
re.regex($e.target.hostname, `client-[0-9]+`) nocase

如果欄位類型是列舉值,就無法使用 nocase 修飾符。下列範例無效,會產生編譯錯誤:

$e.metadata.event_type = "NETWORK_DNS" nocase
$e.network.ip_protocol = "TCP" nocase

註解

您可以在查詢中使用註解提供更多資訊。您可以使用正斜線字元表示註解:

  • 如要新增單行註解,請使用兩個正斜線字元 (// comment)。
  • 如要加入多行註解,請使用一個正斜線字元和星號字元 (/* comment */)。

文字

YARA-L 支援非負整數和浮點數、字串、布林值和規則運算式常值。常值是查詢條件中使用的固定值。YARA-L 也會使用其他類似字元的建構體,例如用於模式比對的規則運算式 (以正斜線括住),以及用於邏輯的布林值 (true/false)。

字串常值

字串常值是括在雙引號 (") 或反引號 (`) 中的字元序列。字串的解讀方式會因使用的引號類型而異:

  • 半形雙引號 ("hello\tworld"):用於一般字串,必須包含逸出字元,其中 \t 會解讀為 Tab 鍵。
  • 反引號 (`hello\tworld`):用於所有字元都應解讀為常值的情況,其中 \t 不會解讀為 Tab 鍵。

規則運算式常值

對於規則運算式常值,您有兩種做法:

  • 如要直接使用規則運算式,而不使用 re.regex() 函式,請使用 /regex/ 做為規則運算式常值。

  • 如要將字串常值做為規則運算式常值使用,請使用 re.regex() 函式。請注意,如果是雙引號字串常值,您必須使用反斜線字元逸出反斜線字元,這可能會看起來很奇怪。

以下範例顯示等效的規則運算式:

re.regex($e.network.email.from, `.*altostrat\.com`)

re.regex($e.network.email.from, ".*altostrat\\.com")

$e.network.email.from = /.*altostrat\.com/

Google 建議在規則運算式中使用反引號字元表示字串,方便讀取。

運算子

運算子 說明
= equal/declaration
!= 不等於
< 小於
<= 小於或等於
> 大於
>= 大於或等於

變數

在 YARA-L 中,所有變數都使用 $<variable name> 語法。YARA-L 可使用下列類型的變數。

事件變數

事件變數代表事件群組或實體事件。您可以在 events 區段中,使用名稱、事件來源和事件欄位,指定事件變數的條件。

  • 事件來源為 udm (適用於標準化事件) 和 graph (適用於實體事件)。如果省略來源,系統會將 udm 設為預設來源。

  • 事件欄位會以 .<欄位名稱> 鏈結表示 (例如 $e.field1.field2),且欄位鏈結一律從頂層來源 (UDM 或實體) 開始。

比對變數

「比對變數」用於 match 區段,根據指定時間範圍內的共同值將事件分組。

這些欄位會成為查詢的分組欄位,因為系統會為每組不重複的相符變數 (以及每個時間範圍) 傳回一個資料列。查詢找到相符項目時,系統會傳回相符變數值。

您可以在 events 區段中指定每個比對變數代表的內容。

預留位置變數

預留位置變數可用來擷取及儲存 UDM 事件欄位的特定值,以便在整個查詢中參照及使用。這類 ID 可用於連結不同的事件,特別是在多事件查詢中。只要將通用值 (例如 useridhostname) 指派給預留位置,您就能在 match 區段中使用這個預留位置,將指定時間範圍內共用該值的事件分組。

您可以在 events 區段中定義預留位置變數,方法是將 UDM 欄位的值指派給以 $ 為前置字元的變數名稱 (例如:$targetUser = $e.target.user.userid)。

您也可以在下列部分定義預留位置變數:

  • condition 部分指定比對條件。
  • outcome 區段,執行計算、定義指標,或從相符事件中擷取特定資料點。
  • 部分,依共同值將事件分組。match

關鍵字

在 YARA-L 中,關鍵字是保留字,用於定義偵測查詢的結構和邏輯。這些運算子可用於指定查詢的不同區段、執行邏輯和數學運算,以及定義相符事件的條件。這些關鍵字無法做為查詢、字串或變數的 ID。

關鍵字不區分大小寫 (例如 andAND 效果相同)。

YARA-L 2.0 關鍵字的主要類別

這份清單並未列出所有關鍵字,但涵蓋 YARA-L 2.0 中用於建構強大偵測查詢的主要關鍵字。

  • 查詢定義:
    • rule:啟動新 YARA-L 查詢的定義。
    • private:將查詢指定為私密,防止查詢直接公開或從外部觸發。
    • global:將查詢標示為全域,表示應廣泛套用。
  • 查詢區段:
    • meta:介紹中繼資料部分,其中包含查詢的說明資訊。
    • strings:表示定義字串模式的部分。
    • condition:指定包含查詢觸發布林邏輯的區段。
    • events:定義用於指定事件變數及其條件的區段。
    • match:介紹用於彙整時間範圍內值的區段。
    • outcome:定義區段,以便為觸發的查詢新增內容和評分。
  • 字串修飾符:
    • ascii:指定字串應比對為 ASCII 文字。
    • wide:表示字串應比對為全形 (UTF-16) 字元。
    • nocase:執行不區分大小寫的字串比對。
    • fullword:要求字串必須完全相符。
    • xor:在比對字串前,先對字串套用 XOR 轉換。
    • base64base64wide:先套用 Base64 編碼,再進行比對。
  • 邏輯運算子:
    • andornot:用於合併條件的標準布林邏輯運算子。
    • all ofany of:用於評估條件中的多個運算式。
  • 比較和關係運算子:
    • at:指定字串比對的確切偏移。
    • contains:檢查字串是否包含子字串。
    • startswithendswith:檢查字串是否以子字串開頭或結尾。
    • icontainsistartswithiendswithiequals:不區分大小寫的版本。
    • matches:用於規則運算式比對。
  • 資料類型和大小指定符:
    • int8uint8int16uint16int32uint32:指定大小的整數型別。
    • int8beuint8beint16beuint16beint32beuint32be:整數型別的大端版本。
    • filesize:代表要分析的檔案大小。
    • entrypoint:指可執行檔的進入點。

地圖

YARA-L 支援 StructLabel 資料類型的對應,這兩種資料類型用於部分 UDM 欄位。

如要在 Struct 和 Label 資料類型中搜尋特定鍵/值組合,請使用標準對應語法:

  • 結構體欄位語法:$e.udm.additional.fields["pod_name"] = "kube-scheduler"
  • 標籤欄位語法:$e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"

示例:地圖的有效和無效使用方式

以下範例說明地圖的有效和無效用法。

地圖的有效用途

在「事件」部分使用 Struct 欄位:

events:
  $e.udm.additional.fields["pod_name"] = "kube-scheduler"
  

在結果部分使用「標籤」欄位:

outcome:
  $value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])
 

將地圖值指派給預留位置:

$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]

在聯結條件中使用對應欄位:

// using a Struct field in a join condition between two udm events $u1 and $u2
$u1.metadata.event_type = $u2.udm.additional.fields["pod_name"]

不支援的地圖用途

anyall 關鍵字與地圖合併

all $e.udm.additional.fields["pod_name"] = "kube-scheduler"

其他類型的值

對應語法只能傳回字串值。如果是 [Struct](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#struct) 資料類型,地圖語法只能存取值為字串的鍵。您無法存取值為其他原始型別 (例如整數) 的鍵。

地圖中的重複值處理方式

地圖存取作業的目的是擷取與特定鍵相關聯的單一值。這是預期中的標準行為。 不過,在極少數情況下,map access 的內容可能會意外指向多個值。在罕見的極端情況下,如果地圖存取是指多個值,map access 會確定傳回第一個值。如果標籤有重複的鍵,或是標籤有重複的祖先欄位,就可能會發生這種情況。

標籤的鍵重複

標籤結構代表對應,但不會強制執行鍵的唯一性。按照慣例,地圖應具有不重複的鍵,因此 Google SecOps 不建議使用重複的鍵填入標籤。

範例:含有重複鍵的標籤

如果對下列資料範例執行查詢文字 $e.metadata.ingestion_labels["dupe-key"],會傳回第一個可能的值 val1

    // Disrecommended usage of label with a duplicate key:
    event {
      metadata{
        ingestion_labels{
          key: "dupe-key"
          value: "val1" // This is the first possible value for "dupe-key"
        }
        ingestion_labels{
          key: "dupe-key"
          value: "val2"
        }
      }
    }
  

標籤含有祖先重複欄位

重複欄位可能包含標籤做為子項欄位。頂層重複欄位中的兩個不同項目可能含有鍵相同的標籤。

範例:含有祖先重複欄位的標籤

如果對下列資料範例執行查詢文字 $e.security_result.rule_labels["key"],系統會傳回第一個可能的值 `val3`:

    event {
      // security_result is a repeated field.
      security_result {
        threat_name: "threat1"
        rule_labels {
          key: "key"
          value: "val3" // This is the first possible value for "key"
        }
      }
      security_result {
        threat_name: "threat2"
        rule_labels {
          key: "key"
          value: "val4"
        }
      }
    }
  

在地圖中存取結果變數

本節說明如何以原始資料型別 (例如整數、布林值或這些型別的清單),而非僅以字串形式存取地圖中的結果變數。您可以運用這項功能,更彈性且準確地查詢邏輯。

結果資料會顯示在下列欄位中:

  • variables 欄位中的結果值會保留原始類型。
  • outcomes 欄位會儲存 string 版本,以確保回溯相容性。

您可以使用 variables 對應項存取這些結果值,以擷取特定型別,或使用陣列索引編號存取序列中的元素。您可以依索引存取序列中的特定項目,也可以選取整個序列,個別評估每個值。

語法

$d.detection.detection.variables[OUTCOME_NAME].TYPE_SUFFIX

序列語法

$d.detection.detection.variables[OUTCOME_NAME].SEQUENCE_TYPE_SUFFIX.TYPE_VALS_SUFFIX

範例:在地圖中存取結果變數

存取字串結果:

    $my_string_outcome = $d.detection.detection.variables["outcome_ip"].string_val
   

這個範例會直接擷取字串值 (例如,如果 outcome_ip 是單一字串,則為 "1.1.1.1")。

存取整數結果

    $my_int_outcome = $d.detection.detection.variables["outcome_port"].int64_value
    

這個範例會擷取整數值 (例如 30)。

使用 Int64Sequence 存取整數清單

   $my_int_list = $d.detection.detection.variables["outcome_ports"].int64_seq.int64_vals
   

這個範例會擷取完整的整數清單,並取消巢狀結構,例如重複欄位 (例如 [2, 3, 4])。

從整數清單存取特定元素

    $first_int = $d.detection.detection.variables["outcome_ports"].int64_seq.int64_vals[0]
    

這個範例會從清單中擷取第一個整數 (例如 2)。

存取字串清單 (StringSequence)

    $my_string_list = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals
    

這個範例會擷取完整的字串清單,並取消巢狀結構,例如重複欄位 (例如 ["1.1.1.1", "2.2.2.2"])。

從字串清單存取特定元素

    $first_ip = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals[0]
    

這個範例會從清單中擷取第一個 IP 位址 (例如 "1.1.1.1")。

variables 可用的類型後置字元

如需支援的完整後置字元清單,請參閱「FindingVariable」。

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