Champs répétés

Compatible avec :

Dans le modèle de données unifié (UDM), certains champs sont marqués comme répétés, ce qui indique qu'il s'agit de listes de valeurs ou d'autres types de messages. Ce document explique comment utiliser des expressions, des espaces réservés, l'indexation de tableaux et les messages répétés pour les champs UDM répétés.

Expressions booléennes et champs répétés

Les expressions booléennes modifiées et non modifiées peuvent agir sur les champs répétés.

Prenons l'exemple suivant :

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

    hostname: "host"
  }
}

Expressions modifiées

Utilisez les modificateurs any et all dans les expressions des champs répétés.

  • any : si un élément du champ répété remplit la condition, l'événement dans son ensemble remplit la condition. Exemple :

    • event_original satisfait any $e.principal.ip = "192.0.2.1"
    • Échec de event_original any $e.repeated_field.field_a = "9.9.9.9"
  • all : si tous les éléments du champ répété remplissent la condition, l'événement dans son ensemble remplit la condition. Exemple :

    • event_original satisfait net.ip_in_range_cidr(all $e.principal.ip, "192.0.2.0/8")
    • Échec de event_original all $e.principal.ip = "192.0.2.2"

Lorsque vous écrivez une condition avec any ou all, sachez que nier la condition avec not peut ne pas avoir la même signification que d'utiliser l'opérateur de négation.

Exemple :

  • not all $e.principal.ip = "192.168.12.16" vérifie si toutes les adresses IP ne correspondent pas à 192.168.12.16, ce qui signifie que la requête vérifie qu'au moins une adresse IP ne correspond pas à 192.168.12.16.
  • all $e.principal.ip != "192.168.12.16" vérifie si toutes les adresses IP ne correspondent pas à 192.168.12.16, ce qui signifie que la requête vérifie qu'aucune adresse IP ne correspond à 192.168.12.16.

Contraintes :

  • Les opérateurs any et all ne sont compatibles qu'avec les champs répétés (et non avec les champs scalaires).
  • any et all ne peuvent pas être utilisés pour joindre deux champs répétés. Par exemple, any $e1.principal.ip = $e2.principal.ip n'est pas valide.
  • Les opérateurs any et all ne sont pas compatibles avec l'expression de la liste de référence.

Expressions non modifiées

Avec les expressions non modifiées, chaque élément du champ répété est traité individuellement. Si le champ répété d'un événement contient n éléments, la requête est appliquée à n copies de l'événement, où chaque copie comporte l'un des éléments du champ répété. Ces copies sont temporaires et ne sont pas stockées.

La règle s'applique aux copies suivantes :

copie d'événement 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"

Si une copie d'événement répond à toutes les conditions non modifiées du champ répété, l'événement dans son ensemble répond à toutes les conditions. Par conséquent, si vous avez plusieurs conditions sur un champ répété, une seule copie d'événement doit satisfaire toutes ces conditions. Les exemples de requêtes suivants utilisent l'ensemble de données précédent pour illustrer ce comportement.

Exemple : Expressions non modifiées

La règle suivante renvoie une correspondance lorsqu'elle est exécutée sur l'exemple d'ensemble de données event_original, car event_copy_1 satisfait à tous les prédicats d'événements :

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
}

La règle suivante ne renvoie aucune correspondance lorsqu'elle est exécutée sur l'exemple de jeu de données event_original, car aucune copie d'événement dans $e.principal.ip ne satisfait _tous_ les prédicats d'événement.

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

Les expressions modifiées sur les champs répétés sont compatibles avec les expressions non modifiées sur les champs répétés, car la liste des éléments est la même pour chaque copie d'événement. Prenons l'exemple de règle suivant :

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

La règle s'applique aux copies suivantes :

copie d'événement 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"]

Dans ce cas, toutes les copies satisfont any $e.principal.ip = "192.0.2.1", mais seule event_copy_3 satisfait $e.principal.ip = "192.0.2.3". L'événement dans son ensemble correspondrait alors.

Voici une autre façon de considérer ces types d'expressions :

  • Les expressions sur les champs répétés qui utilisent any ou all fonctionnent sur la liste dans event_original.
  • Les expressions sur les champs répétés qui n'utilisent pas any ni all fonctionnent sur des événements event_copy_n individuels.

Espaces réservés et champs répétés

Les champs répétés fonctionnent avec les attributions d'espace réservé. Comme pour les expressions non modifiées sur les champs répétés, une copie de l'événement est créée pour chaque élément. En reprenant l'exemple de event_copy, le code de substitution prend la valeur du champ répété de event_copy_n, pour chacune des copies d'événement où n correspond au numéro de la copie d'événement. Si l'espace réservé est utilisé dans la section "Correspondance", cela peut entraîner plusieurs correspondances.

Exemple : Espace réservé pour un champ répété

L'exemple suivant génère une correspondance. L'espace réservé `$ip` est égal à `192.0.2.1` pour `event_copy_1`, ce qui satisfait les prédicats de la règle. Les exemples d'événements de la correspondance ne contiennent qu'un seul élément, "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
}

L'exemple suivant génère trois correspondances. L'espace réservé $ip est égal à différentes valeurs pour chacune des différentes copies event_copy_n. Le regroupement est effectué sur $ip, car il se trouve dans la section "Correspondances". Vous obtenez donc trois correspondances, chacune ayant une valeur différente pour la variable de correspondance $ip. Chaque correspondance comporte le même échantillon d'événement : un seul élément, 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
}

Résultats utilisant des espaces réservés attribués à des champs répétés

Des espaces réservés sont attribués à chaque élément de chaque champ répété, et non à la liste entière. Lorsqu'ils sont utilisés dans la section outcome, le résultat est calculé en utilisant uniquement les éléments qui ont satisfait aux sections précédentes.

Prenons l'exemple de règle suivant :

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
}

Cette règle comporte quatre étapes d'exécution. La première étape consiste à copier les événements :

copie d'événement $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

La section "Événements" filtrera ensuite les lignes qui ne correspondent pas aux filtres :

copie d'événement $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 est filtré, car "192.0.2.3" ne respecte pas $ip = "192.0.2.1" or $ip = "192.0.2.2".

La section match regroupe ensuite les données par variables de correspondance, et la section outcome effectue l'agrégation sur chaque groupe :

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

$o = array_distinct($ip) est calculé à l'aide de $ip de l'étape précédente, et non de l'étape de copie des événements.

Enfin, la section condition filtrera chaque groupe. Étant donné que cette règle vérifie simplement l'existence de $e, la ligne précédente générera une seule détection.

$o ne contient pas tous les éléments de $e.principal.ip, car tous les éléments ne remplissaient pas toutes les conditions de la section "Événements". Toutefois, tous les éléments de e.principal.ip apparaîtront dans l'exemple d'événement, car celui-ci utilise event_original.

Indexation de tableau

Vous pouvez effectuer l'indexation de tableaux sur des champs répétés. Pour accéder au n-ième élément de champ répété, utilisez la syntaxe de liste standard (les éléments sont indexés à partir de 0). Un élément hors limites renvoie la valeur par défaut.

  • $e.principal.ip[0] = "192.168.12.16"
  • $e.principal.ip[999] = "" Si le nombre d'éléments est inférieur à 1 000, la valeur renvoyée est true.

Contraintes :

  • Un index doit être un littéral entier non négatif. Par exemple, $e.principal.ip[-1] n'est pas valide.
  • Les valeurs de type int (par exemple, un espace réservé défini sur int) ne sont pas comptabilisées.
  • L'indexation de tableaux ne peut pas être combinée avec any ni all. Par exemple, any $e.intermediary.ip[0] n'est pas valide.
  • L'indexation de tableaux ne peut pas être combinée à la syntaxe de carte. Par exemple, $e.additional.fields[0]["key"] n'est pas valide.
  • Si le chemin d'accès au champ contient plusieurs champs répétés, tous les champs répétés doivent utiliser l'indexation de tableau. Par exemple, $e.intermediary.ip[0] n'est pas valide, car intermediary et ip sont tous les deux des champs répétés, mais il n'existe qu'un index pour ip.

Messages répétés

Lorsqu'un champ message est répété, cela réduit involontairement la probabilité d'une correspondance. Ce processus est illustré dans les exemples suivants.

Prenons l'exemple suivant :

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"
  }
}

Comme indiqué pour les expressions non modifiées sur les champs répétés, une copie temporaire de l'événement est créée pour chaque élément du champ répété. Prenons l'exemple de règle suivant :

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

La règle s'applique aux copies suivantes :

copie d'événement 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"

L'événement ne correspond pas à la règle, car il n'existe aucune copie d'événement qui satisfasse toutes les expressions.

Messages répétés et indexation de tableaux

Un autre comportement inattendu peut se produire lorsque vous utilisez l'indexation de tableaux avec des expressions non modifiées sur des champs de messages répétés. Prenons l'exemple de règle suivant, qui utilise l'indexation de tableau :

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

La règle s'applique aux copies suivantes :

copie d'événement 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"

Étant donné que event_copy_1 satisfait toutes les expressions de repeated_message_2, l'événement correspond à la règle.

Cela peut entraîner un comportement inattendu, car la règle repeated_message_1 ne comportait pas d'indexation de tableau et n'a produit aucune correspondance, tandis que la règle repeated_message_2 utilisait l'indexation de tableau et a produit une correspondance.

Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.