Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

Syntaxe du langage YARA-L 2.0

Cette section décrit les principaux éléments de la syntaxe YARA-L. Consultez également Présentation de la langue YARA-L 2.0.

Structure de la règle

Pour YARA-L 2.0, vous devez spécifier les déclarations, les définitions et les utilisations de variables dans l'ordre suivant:

  1. méta
  2. événement
  3. correspondance (facultatif)
  4. résultat (facultatif)
  5. condition
  6. options (facultatif)

Voici la structure générique d'une règle:

rule <rule Name>
{
  meta:
    // Stores arbitrary key-value pairs of rule details, such as who wrote
    // it, what it detects on, version control, etc.

  events:
    // Conditions to filter events and the relationship between events.

  match:
    // Values to return when matches are found.

  outcome:
    // Additional information extracted from each detection.

  condition:
    // Condition to check events and the variables used to find matches.

  options:
    // Options to turn on or off while executing this rule.
}

Commentaires

Désignez des commentaires comportant deux barres obliques (// comment) ou des commentaires multilignes à l'aide d'un astérisque (/* comment */), comme vous le feriez pour C.

Littéraux

Les entiers non négatifs (sans points décimaux), les littéraux de chaîne, booléens et d'expression régulière sont acceptés.

Littéraux de chaîne et d'expression régulière

Vous pouvez utiliser l'un des guillemets suivants pour délimiter des chaînes dans YARA-L 2.0. Toutefois, le texte des guillemets est interprété différemment selon l'option que vous utilisez.

  1. Doubles guillemets (") : à utiliser pour les chaînes normales. Doit inclure des caractères d'échappement.
    Par exemple : "hello\tworld" —\t" est interprété comme un onglet

  2. Guillemets arrière (`) : permettent d'interpréter tous les caractères de manière littérale.
    Par exemple : "hello\tworld" :\t n'est pas interprété comme un onglet.

Vous disposez de deux options pour les expressions régulières.

Si vous souhaitez utiliser des expressions régulières directement sans la fonction re.regex(), utilisez /regex/ pour les littéraux d'expressions régulières.

Vous pouvez également utiliser des littéraux de chaîne en tant que littéraux d'expression régulière lorsque vous utilisez la fonction re.regex(). Notez que pour les littéraux de chaîne entre guillemets doubles, vous devez échapper les barres obliques inverses contenant des barres obliques inverses, ce qui peut sembler gênant.

Par exemple, les expressions régulières suivantes sont équivalentes:

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

Pour faciliter la lecture, Google recommande d'utiliser des guillemets pour les chaînes dans les expressions régulières.

Opérateurs

Vous pouvez utiliser les opérateurs suivants dans YARA-L:

Opérateur Description
= égal/déclaration
!= différent de
< inférieur à
<= inférieur ou égal à
> supérieur à
>= supérieur ou égal à

Variables

Dans YARA-L 2.0, toutes les variables sont représentées par $<variable name>.

Vous pouvez définir les types de variables suivants:

  • Variables d'événement : représentent des groupes d'événements au format normalisé (UDM) ou des événements d'entité. Spécifiez les conditions associées aux variables d'événements dans la section events. Pour identifier les variables d'événement, utilisez un nom, une source d'événements et des champs d'événement. Les sources autorisées sont udm (pour les événements normalisés) et graph (pour les événements d'entité). Si la source est omise, udm est défini comme source par défaut. Les champs d'événement sont représentés par une chaîne .<field name> (par exemple, $e.field1.field2). Les chaînes de champs d'événement commencent toujours par la source principale (UDM ou entité).

  • Variables de correspondance : déclarez-les dans la section match. Les variables de correspondance deviennent des champs de regroupement pour la requête, car une ligne est renvoyée pour chaque ensemble unique de variables de correspondance (et pour chaque fenêtre temporelle). Lorsque la règle trouve une correspondance, les valeurs des variables de correspondance sont renvoyées. Spécifiez ce que chaque variable de correspondance représente dans la section events.

  • Variables d'espace réservé : déclarez et définissez dans la section events. Les variables fictives sont semblables aux variables correspondantes. Toutefois, vous pouvez utiliser des variables dans la section condition pour spécifier des conditions de correspondance.

Utilisez des variables de correspondance et des espaces réservés pour déclarer des relations entre les champs d'événement via des conditions de jointure transitives (pour en savoir plus, consultez la section Syntaxe de la section "Événements").

Maps

Structures et étiquettes

Certains champs UDM utilisent le type de données Structureou Libellé.

Pour rechercher une paire clé-valeur spécifique à la fois dans Struct et dans Label, utilisez la syntaxe de mappage standard:

// A Struct field.
$e.udm.additional.fields["pod_name"] = "kube-scheduler"
// A Label field.
$e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"

Demandes acceptées

Section "Événements et résultats"
// Using a Struct field in the events section
events:
  $e.udm.additional.fields["pod_name"] = "kube-scheduler"

// Using a Label field in the outcome section
outcome:
  $value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])
Attribuer une valeur de mappage à un espace réservé
$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]
Utiliser un champ de mappage dans une condition de jointure
// 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"]

Demandes non acceptées

Combiner des mots clés any ou all avec une carte

Par exemple, les éléments suivants ne sont actuellement pas acceptés : all $e.udm.additional.fields["pod_name"] = "kube-scheduler"

Fonctions

Cette section décrit les fonctions YARA-L 2.0 compatibles avec Chronicle dans le moteur de détection.

Ces fonctions peuvent être utilisées dans les domaines suivants d'une règle:

Fonctions de chaîne

Chronicle est compatible avec les fonctions de manipulation de chaînes suivantes:

  • string.concat(a, b)
  • string.to_lower(stringText)
  • string.to_upper(chaîneText)
  • string.base64_decode(StringString)

Les sections suivantes expliquent comment les utiliser.

Concaténer des chaînes ou des entiers

Renvoie la concaténation de deux chaînes, de deux entiers ou d'une combinaison des deux.

strings.concat(a, b)

Cette fonction accepte deux arguments, qui peuvent être des chaînes ou des entiers, et renvoie les deux valeurs concaténées sous forme de chaîne. Les entiers sont convertis en chaîne avant la concaténation. Les arguments peuvent être des littéraux ou des champs d'événement. Si les deux arguments sont des champs, les deux attributs doivent provenir du même événement.

L'exemple suivant inclut une variable de chaîne et un littéral de chaîne en tant qu'arguments.

"google-test" = strings.concat($e.principal.hostname, "-test")

L'exemple suivant inclut une variable de chaîne et une variable d'entier. "principal.hostname" et "principal.port" proviennent du même événement, $e, et sont concaténés pour renvoyer une chaîne.

"google80" = strings.concat($e.principal.hostname, $e.principal.port)

L'exemple suivant tente de concaténer le compte principal.port de l'événement $e1, avec le compte principal.hostname de l'événement $e2. Il renverra une erreur de compilateur, car les arguments sont des variables d'événements différentes.

// returns a compiler error
"test" = strings.concat($e1.principal.port, $e2.principal.hostname)

Convertir une chaîne en majuscules ou en minuscules

Ces fonctions renvoient du texte de chaîne après la modification de tous les caractères, en majuscules ou en minuscules.

  • string.to_lower(stringText)
  • string.to_upper(chaîneText)
"test@google.com" = strings.to_lower($e.network.email.from)
"TEST@GOOGLE.COM" = strings.to_upper($e.network.email.to)

Décoder une chaîne en base64

Renvoie une chaîne contenant la version décodée en base64 de la chaîne encodée.

strings.base64_decode(encodedString)

Cette fonction utilise une chaîne encodée en base64 comme argument. Si encodedString n'est pas une chaîne encodée en base64 valide, la fonction renvoie encodedString tel quel.

Cet exemple renvoie la valeur "True" si principal.domain.name est "dGVzdA=\tquot;, qui est l'encodage base64 de la chaîne "test".

"test" = strings.base64_decode($e.principal.domain.name)

Fonctions RegExp

Chronicle est compatible avec les fonctions d'expression régulière suivantes:

  • re.expression(stringText, expression régulière)
  • re.capture(stringText, expression régulière)
  • re.replace(stringText, replaceRegex, replaceText)

Correspondance avec expression régulière

Vous pouvez définir la correspondance d'expression régulière dans YARA-L 2.0 à l'aide de l'une des syntaxes suivantes:

  • Utilisation de la syntaxe YARA : liée aux événements. Voici une représentation générique de cette syntaxe : $e.field = /regex/
  • Utilisation de la syntaxe YARA-L en tant que fonction utilisant les paramètres suivants :
    • Champ auquel l'expression régulière est appliquée.
    • Expression régulière spécifiée sous forme de chaîne. Vous pouvez utiliser le modificateur nocase après les chaînes pour indiquer que la recherche doit ignorer les majuscules. Voici une représentation générique de cette syntaxe : re.regex($e.field, `regex`)

Tenez compte des points suivants lorsque vous définissez des expressions régulières dans YARA-L 2.0:

  • Dans les deux cas, le prédicat est vrai si la chaîne contient une sous-chaîne correspondant à l'expression régulière fournie. Il n'est pas nécessaire d'ajouter .* au début ou à la fin de l'expression régulière.
  • Pour correspondre exactement à la chaîne, ou seulement à un préfixe ou à un suffixe, incluez les caractères d'ancrage ^ (début) et $ (fin) dans l'expression régulière. Par exemple, /^full$/ correspond exactement à "full", tandis que /full/ peut correspondre à "fullest", "lawfull" et "joyfully".
  • Si le champ UDM comprend des caractères de nouvelle ligne, regexp ne correspond qu'à la première ligne du champ UDM. Pour appliquer la correspondance complète des champs UDM, ajoutez un (?s) à l'expression régulière. Par exemple, remplacez /.*allUDM.*/ par /(?s).*allUDM.*/.

Capture de l'expression régulière

Capture (extrait) les données d'une chaîne à l'aide du modèle d'expression régulière fourni dans l'argument.

re.capture(stringText, regex)

Cette fonction comporte deux arguments:

  • stringText: chaîne d'origine à rechercher.
  • expression régulière: expression régulière indiquant le modèle à rechercher.

L'expression régulière peut contenir 0 ou 1 groupe de capture entre parenthèses. Si l'expression régulière contient 0 groupe de capture, la fonction renvoie la première sous-chaîne correspondante. Si l'expression régulière contient un groupe de capture, elle renvoie la première sous-chaîne du groupe de capture. La définition de deux groupes de capture ou plus renvoie une erreur de compilateur.

Dans cet exemple, si $e.principal.hostname contient "aaa1bbaa2" ce qui suit serait True, car la fonction renvoie la première instance. Cet exemple ne comporte aucun groupe de capture.

"aaa1" = re.capture($e.principal.hostname, "a+[1-9]")

Cet exemple montre tout ce qui suit le symbole @ dans un e-mail. Si le champ $e.network.email.from est test@google.com, l'exemple renvoie google.com. Cet exemple contient un groupe de capture.

"google.com" = re.capture($e.network.email.from , "@(.*)")

Si l'expression régulière ne correspond à aucune sous-chaîne du texte, la fonction renvoie une chaîne vide. Vous pouvez omettre les événements où aucune correspondance ne se produit en excluant la chaîne vide, ce qui est particulièrement important lorsque vous utilisez re.capture() avec une inégalité:

// Exclude the empty string to omit events where no match occurs.
"" != re.capture($e.network.email.from , "@(.*)")

// Exclude a specific string with an inequality.
"google.com" != re.capture($e.network.email.from , "@(.*)")

Remplacement d'expression régulière

Effectue un remplacement d'expression régulière.

re.replace(stringText, replaceRegex, replacementText)

Cette fonction comporte trois arguments:

  • stringText: chaîne d'origine.
  • replaceRegex: expression régulière indiquant le modèle à rechercher.
  • remplacementText: texte à insérer dans chaque correspondance.

Renvoie une nouvelle chaîne dérivée de la chaîne d'origine stringText, dans laquelle toutes les sous-chaînes correspondant au modèle dans replaceRegex sont remplacées par la valeur dans replacementText. Vous pouvez utiliser des chiffres échappés par une barre oblique inverse (\1 à \9) dans replacementText pour insérer du texte correspondant au groupe entre parenthèses correspondant dans le modèle replaceRegex. Utilisez \0 pour faire référence à l'ensemble du texte associé.

La fonction remplace les correspondances qui ne se chevauchent pas et donne la priorité à la première occurrence trouvée. Par exemple, re.replace(, banane, anana, 111) renvoie la chaîne b111na.

Cet exemple capture tout ce qui se trouve après le symbole @ dans un e-mail, remplace com par org, puis renvoie le résultat. Notez l'utilisation de fonctions imbriquées.

"email@google.org" = re.replace($e.network.email.from, "com", "org")

Cet exemple utilise des chiffres échappés par une barre oblique inverse dans l'argument replaceText pour faire référence aux correspondances avec le modèle replaceRegex.

"test1.com.google" = re.replace(
                       $e.principal.hostname, // holds "test1.test2.google.com"
                       "test2\.([a-z]*)\.([a-z]*)",
                       "\\2.\\1"  // \\1 holds "google", \\2 holds "com"
                     )

Notez les cas suivants en cas de chaînes vides et de re.replace() :

Utilisation de la chaîne vide en tant que replaceRegex:

// In the function call below, if $e.principal.hostname contains "name",
// the result is: 1n1a1m1e1, because an empty string is found next to
// every character in `stringText`.
re.replace($e.principal.hostname, "", "1")

Pour remplacer une chaîne vide, vous pouvez utiliser "^$" comme replaceRegex:

// In the function call below, if $e.principal.hostname contains the empty
// string, "", the result is: "none".
re.replace($e.principal.hostname, "^$", "none")

Fonctions de date

Chronicle est compatible avec les fonctions liées à la date suivantes:

  • timestamp.get_minute(unix_seconds [, time_zone])
  • timestamp.get_hour(unix_seconds [, time_zone])
  • timestamp.get_day_of_week(unix_seconds [, time_zone])
  • timestamp.get_week(unix_seconds [, time_zone])
  • timestamp.current_seconds()

Chronicle accepte les entiers négatifs en tant qu'argument unix_seconds. Les entiers négatifs représentent les temps précédant l'époque Unix. Si vous fournissez un entier non valide, par exemple une valeur qui entraîne un débordement, la fonction renvoie "-1". Ce scénario est peu courant.

Étant donné que YARA-L 2 n'accepte pas les littéraux entiers négatifs, veillez à rechercher cette condition à l'aide de l'opérateur "inférieur à" ou "supérieur à". Exemple :

0 > timestamp.get_hour(123)

Extraction de données temporelles

Renvoie un entier compris dans la plage [0, 59].

timestamp.get_minute(unix_seconds [, time_zone])

La fonction suivante renvoie un entier compris dans la plage [0, 23], représentant l'heure de la journée.

timestamp.get_hour(unix_seconds [, time_zone])

La fonction suivante renvoie un entier compris dans la plage [1, 7] qui représente le jour de la semaine commençant par le dimanche. Exemples : 1 = dimanche ; 2 = lundi.

timestamp.get_day_of_week(unix_seconds [, time_zone])

La fonction suivante renvoie un entier compris dans la plage [0, 53] représentant la semaine de l'année. Les semaines commencent le dimanche. Les dates antérieures au premier dimanche de l'année correspondent à la semaine 0.

timestamp.get_week(unix_seconds [, time_zone])

Ces fonctions d'extraction de temps ont les mêmes arguments.

  • unix_seconds est un entier représentant le nombre de secondes après l'époque Unix, tel que $e.metadata.event_timestamp.seconds, ou un espace réservé contenant cette valeur.
  • "time_zone" est facultatif et correspond à une chaîne représentant un fuseau horaire. Si vous l'omettez, la valeur par défaut est "GMT". Vous pouvez spécifier des fuseaux horaires à l'aide de littéraux de chaîne. Les options sont les suivantes :
    • Nom de la base de données TZ, par exemple "America/Los_Angeles". Pour en savoir plus, consultez la colonne Nom de la base de données TZ de cette page.
    • Décalage du fuseau horaire par rapport au temps UTC, au format (+|-)H[H][:M[M]] (par exemple, "-08:00").

Dans cet exemple, l'argument time_zone est omis. Il est donc défini par défaut sur "GMT".

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_hour($ts) = 15

Cet exemple utilise un littéral de chaîne pour définir le fuseau horaire.

$ts = $e.metadata.collected_timestamp.seconds

2 = timestamp.get_day_of_week($ts, "America/Los_Angeles")

Voici d'autres spécificateurs de fuseau horaire valides, que vous pouvez transmettre en tant que deuxième argument des fonctions d'extraction de temps:

  • "America/Los_Angeles" ou "-08:00". ("PST" n'est pas compatible)
  • "America/New_York" ou "-05:00". ("EST" n'est pas compatible)
  • "Europe/London"
  • "UTC"
  • "GMT"

Horodatage actuel

Renvoie un nombre entier représentant l'heure actuelle en secondes Unix. Cela correspond à peu près à l'horodatage de la détection et est basé sur le moment où la règle est exécutée.

timestamp.current_seconds()

L'exemple suivant renvoie la valeur "True" si le certificat a expiré depuis plus de 24 heures. Il calcule le décalage temporel en soustrayant les secondes Unix actuelles, puis en les comparant à l'aide d'un opérateur supérieur à.

86400 < timestamp.current_seconds() - $e.network.tls.certificate.not_after

Fonctions mathématiques

Valeur absolue

Renvoie la valeur absolue d'une expression entière.

math.abs(intExpression)

Cet exemple renvoie la valeur "True" si les événements se trouvaient à plus de cinq minutes d'intervalle, quel que soit l'événement qui est survenu en premier. Notez que l'exemple utilise des fonctions imbriquées.

300 < math.abs($e1.metadata.event_timestamp.seconds
               - $e2.metadata.event_timestamp.seconds
      )

Fonctions Net

Renvoie la valeur "true" lorsque l'adresse IP donnée se trouve dans le sous-réseau spécifié.

net.ip_in_range_cidr(ipAddress, subnetworkRange)

Vous pouvez utiliser YARA-L pour rechercher des événements UDM parmi toutes les adresses IP d'un sous-réseau à l'aide de l'instruction net.ip_in_range_cidr(). Les protocoles IPv4 et IPv6 sont tous deux acceptés.

Pour effectuer une recherche dans une plage d'adresses IP, spécifiez un champ UDM IP et une plage CIDR (Classless Inter-Domain Routing). YARA-L peut gérer les champs d'adresse IP au singulier et en répétition.

Exemple IPv4:

net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")

Exemple IPv6:

net.ip_in_range_cidr($e.network.dhcp.yiaddr, "2001:db8::/32")

Consultez un exemple de règle utilisant l'instruction net.ip_in_range_cidr(). Événement unique dans une plage d'adresses IP

Attribution de la fonction à l'espace réservé

Vous pouvez attribuer le résultat d'un appel de fonction à un espace réservé dans la section events. Exemple :

$placeholder = strings.concat($e.principal.hostname, "my-string").

Vous pouvez ensuite utiliser les variables dans les sections match, condition et outcome. Toutefois, l'attribution d'espaces réservés comporte deux limites:

  1. Chaque espace réservé de la fonction à l'espace réservé doit être attribué à une expression contenant un champ d'événement. Par exemple, les exemples suivants sont valides:

    $ph1 = $e.principal.hostname
    $ph2 = $e.src.hostname
    
    // Both $ph1 and $ph2 have been assigned to an expression containing an event field.
    $ph1 = strings.concat($ph2, ".com")
    
    $ph1 = $e.network.email.from
    $ph2 = strings.concat($e.principal.hostname, "@gmail.com")
    
    // Both $ph1 and $ph2 have been assigned to an expression containing an event field.
    $ph1 = strings.to_lower($ph2)
    

    Toutefois, l'exemple ci-dessous n'est pas valide:

    $ph1 = strings.concat($e.principal.hostname, "foo")
    $ph2 = strings.concat($ph1, "bar") // $ph2 has NOT been assigned to an expression containing an event field.
    
  2. L'appel de fonction doit dépendre d'un et exactement un événement. Cependant, plusieurs champs du même événement peuvent être utilisés dans les arguments d'appel de fonction. Par exemple, les éléments suivants sont valides:

    $ph = strings.concat($event.principal.hostname, "string2")

    $ph = strings.concat($event.principal.hostname, $event.src.hostname)

    En revanche, les valeurs suivantes sont incorrectes:

    $ph = strings.concat("string1", "string2")

    $ph = strings.concat($event.principal.hostname, $anotherEvent.src.hostname)

Syntaxe des listes de référence

Pour en savoir plus sur le comportement et la syntaxe des listes de référence, consultez notre page sur les listes de référence.

Vous pouvez utiliser des listes de référence dans les sections events et outcome. Voici la syntaxe permettant d'utiliser différents types de listes de référence dans une règle:

// 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

Vous pouvez également utiliser l'opérateur not avec des listes de référence, comme indiqué ici : not $e.principal.hostname in regex %my_regex_list.

Pour des raisons de performances, le moteur de détection limite l'utilisation des listes de référence. Vous pouvez utiliser jusqu'à sept instructions in dans une règle, et plusieurs types d'instructions in dans la même règle. Deux expressions in sur sept au maximum peuvent utiliser les opérateurs spéciaux regex ou cidr.

L'opérateur nocase ne fonctionne pas avec les listes de référence. Placer nocase après un appel de la liste de référence n'a aucun effet et n'est pas recommandé.

Syntaxe de la section Meta

La section Meta est composée de plusieurs lignes, où chaque ligne définit une paire clé-valeur. Une partie clé doit être une chaîne sans guillemets et une partie de la valeur doit être entre guillemets:

<key> = "<value>"

Voici un exemple de ligne de section meta valide : meta: author = "Chronicle" severity = "HIGH"

Syntaxe de la section "Événements"

Dans la section events, répertoriez les prédicats à spécifier:

  • Que représente chaque correspondance ou variable d'espace réservé ?
  • Expressions binaires simples en tant que conditions
  • Expressions de fonction en tant que conditions
  • Expressions de listes de référence en tant que conditions
  • Opérateurs logiques

Déclarations de variables

Pour les déclarations de variables, utilisez la syntaxe suivante:

  • <EVENT_FIELD> = <VAR>
  • <VAR> = <EVENT_FIELD>

Les deux sont équivalents, comme illustré dans les exemples suivants:

  • $e.source.hostname = $hostname
  • $userid = $e.principal.user.userid

Cette déclaration indique que cette variable représente le champ spécifié pour la variable d'événement. Lorsque le champ d'événement est répété, la variable peut correspondre à n'importe quelle valeur du tableau. Il est également possible d'attribuer plusieurs champs d'événement à une seule variable d'espace réservé ou à une seule correspondance. Il s'agit d'une condition de jointure transitive.

Par exemple, cette agrégation :

  • $e1.source.ip = $ip
  • $e2.target.ip = $ip

équivaut à:

  • $e1.source.ip = $ip
  • $e1.source.ip = $e2.target.ip

Lorsqu'une variable est utilisée, elle doit être déclarée via une déclaration de variable. Si une variable est utilisée sans déclaration, elle est considérée comme une erreur de compilation.

Expressions binaires simples en tant que conditions

Pour utiliser une expression binaire simple comme condition, utilisez la syntaxe suivante:

  • <EXPR> <OP> <EXPR>

L'expression peut être un champ d'événement, une variable, un littéral ou une expression de fonction.

Exemple :

  • $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")

Si les deux côtés sont des littéraux, il s'agit d'une erreur de compilation.

Expressions de fonction en tant que conditions

Certaines expressions de fonction renvoient une valeur booléenne, qui peut être utilisée comme prédicat individuel dans la section events. Ces fonctions sont les suivantes:

  • re.regex()
  • net.ip_in_range_cidr()

Exemple :

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

Expressions de listes de référence en tant que conditions

Vous pouvez utiliser des listes de référence dans la section "Événements". Pour en savoir plus, consultez la section Listes de référence.

Opérateurs logiques

Vous pouvez utiliser les opérateurs logiques and et or dans la section events, comme indiqué dans les exemples suivants:

  • $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"

Par défaut, l'ordre de priorité est le plus élevé au plus bas : not, and, or.

Par exemple, "a or b and c" est évalué comme "a or (b and c)". Si nécessaire, vous pouvez modifier la priorité à l'aide de parenthèses.

Dans la section events, tous les prédicats sont considérés comme and par défaut.

Opérateurs dans les événements

Vous pouvez utiliser les opérateurs avec des types énumérés. Vous pouvez l'appliquer aux règles afin de simplifier et d'optimiser les performances (utilisez un opérateur au lieu de listes de référence).

Dans l'exemple suivant, "USER_UNCATEGORIZED" et "USER_RESOURCE_DELETION" correspondent à 15000 et 15014, ainsi la règle recherchera tous les événements répertoriés:

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

Liste des événements:

  • SUPPRESSION_DE_RESSOURCES_UTILISATEUR
  • USER_RESOURCE_UPDATE_CONTENT
  • USER_RESOURCE_UPDATE_PERMISSIONS
  • STATISTIQUES UTILISATEUR
  • USER_UNCATEGORIZED

Modificateurs

Nocase

Lorsque vous disposez d'une expression de comparaison entre des valeurs de chaîne ou d'une expression régulière, vous pouvez ajouter "nocase" à la fin de l'expression pour ignorer la casse.

  • $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

Il ne peut pas être utilisé lorsqu'un type de champ correspond à une valeur énumérée. Les exemples ci-dessous sont non valides et généreront des erreurs de compilation:

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

Champs répétés

tout, tout

Dans UDM et Entity, certains champs sont libellés comme répétés, ce qui indique qu'il s'agit de listes de valeurs ou d'autres types de messages. Dans YARA-L, chaque élément du champ répété est traité individuellement. Autrement dit, si le champ répété est utilisé dans la règle, nous évaluons la règle pour chaque élément du champ. Cela peut entraîner un comportement inattendu. Par exemple, si une règle contient à la fois $e.principal.ip = "1.2.3.4" et $e.principal.ip = "5.6.7.8" dans la section events, la règle ne génère jamais de correspondance, même si "1.2.3.4" et "5.6.7.8" figurent tous les deux dans principal.ip.

Pour évaluer le champ répété dans son ensemble, vous pouvez utiliser les opérateurs any et all. Lorsque any est utilisé, le prédicat est défini sur "true" si une valeur dans le champ répété répond à la condition. Lorsque all est utilisé, le prédicat est défini sur "true" si toutes les valeurs du champ répété remplissent la condition.

  • any $e.target.ip = "127.0.0.1"
  • all $e.target.ip != "127.0.0.1"
  • re.regex(any $e.about.hostname, `server-[0-9]+`)
  • net.ip_in_range_cidr(all $e.principal.ip, "10.0.0.0/8")

Les opérateurs any et all ne peuvent être utilisés qu'avec des champs répétés. En outre, ils ne peuvent pas être utilisés lors de l'attribution d'un champ répété à une variable d'espace réservé ou lors de la jointure avec un champ d'un autre événement.

Par exemple, any $e.principal.ip = $ip et any $e1.principal.ip = $e2.principal.ip ne sont pas une syntaxe valide. Pour rechercher un champ répété ou le joindre, utilisez $e.principal.ip = $ip. Il y aura une valeur de variable de correspondance ou une jointure pour chaque élément du champ répété.

Lorsque vous écrivez une condition avec any ou all, notez que l'exclusion de la condition avec not peut avoir la même signification que l'utilisation de l'opérateur inversé.

Exemple :

  • not all $e.principal.ip = "192.168.12.16" vérifie si toutes les adresses IP ne correspondent pas à "192.168.12.16". Cela signifie que la règle vérifie si 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 règle vérifie qu'aucune adresse IP ne correspond à "192.168.12.16".

Exigences concernant les jointures de variables d'événements

Toutes les variables d'événement utilisées dans la règle doivent être jointes à toutes les autres variables d'événement de l'une des manières suivantes:

  • directement via une comparaison d'égalité entre les champs d'événement des deux variables d'événement associées, par exemple : $e1.field = $e2.field. L'expression ne doit pas inclure d'appels d'arithmétique ou de fonction.

  • indirectement via une jointure transitive n'impliquant qu'un champ d'événement (voir la déclaration variable pour une définition de "jointure transitive"). L'expression ne doit pas inclure d'appels d'arithmétique ou de fonction.

Par exemple, en supposant que $e1, $e2 et $e3 sont utilisés dans la règle, les sections events suivantes sont valides.

events:
  $e1.principal.hostname = $e2.src.hostname // $e1 joins with $e2
  $e2.principal.ip = $e3.src.ip // $e2 joins with $e3
events:
  // all of $e1, $e2 and $e3 are transitively joined via the placeholder variable $ip
  $e1.src.ip = $ip
  $e2.target.ip = $ip
  $e3.about.ip = $ip
events:
  $e1.principal.hostname = $e2.src.hostname // $e1 joins with $e2

  // Function to event comparison is not a valid join condition for $e1 and $e2,
  // but the whole events section is valid because we have a valid join condition in the first line.
  re.capture($e1.src.hostname, ".*") = $e2.target.hostname

Voici des exemples de sections events non valides.

events:
  // Event to function comparison is an invalid join condition for $e1 and $e2.
  $e1.principal.hostname = re.capture($e2.principal.application, ".*")
events:
  // Event to arithmetic comparison is an invalid join condition for $e1 and $e2.
  $e1.principal.port = $e2.src.port + 1
events:
  $e1.src.ip = $ip
  $e2.target.ip = $ip
  $e3.about.ip = "192.1.2.0" //$e3 is not joined with $e1 or $e2.
events:
  $e1.src.ip = $ip

  // Function to placeholder comparison is an invalid transitive join condition.
  re.capture($e2.target.ip, ".*") = $ip
events:
  $e1.src.port = $port

  // Arithmetic to placeholder comparison is an invalid transitive join condition.
  $e2.principal.port + 800 = $port

Correspondance avec la syntaxe de la section

Dans la section match, répertoriez les variables de correspondance pour les événements de groupe avant de vérifier les conditions de correspondance. Ces champs sont renvoyés pour chaque correspondance.

  • Spécifiez ce que chaque variable de correspondance représente dans la section events.
  • Indiquez la période à utiliser pour corréler les événements après le mot clé over. Les événements en dehors de cette période sont ignorés.
  • Utilisez la syntaxe suivante pour spécifier la période : <number><s/m/h/d>s/m/h/d signifie respectivement les secondes, les minutes, les heures et les jours.
  • Vous pouvez indiquer une durée minimale d'une minute.
  • La durée maximale que vous pouvez spécifier est de 48 heures.

Voici un exemple de match valide :

$var1, $var2 over 5m

Cette instruction renvoie $var1 et $var2 (définis dans la section events) lorsque la règle trouve une correspondance. La durée spécifiée est de 5 minutes. Les événements éloignés de plus de cinq minutes ne sont pas corrélés et sont donc ignorés par la règle.

Voici un autre exemple de propriété match valide :

$user over 1h

Cette instruction renvoie $user lorsque la règle trouve une correspondance. Le délai spécifié est d'une heure. Les événements espacés d'une heure ne sont pas corrélés. Elles ne sont pas considérées comme une détection.

Voici un autre exemple de propriété match valide:

$source_ip, $target_ip, $hostname over 2m

Cette instruction renvoie $source_ip, $target_ip et $hostname lorsque la règle trouve une correspondance. Le délai spécifié est de deux minutes. Les événements espacés de plus de deux minutes ne sont pas corrélés. Elles ne sont pas considérées comme une détection.

Les exemples suivants illustrent des sections match non valides:

  • var1, var2 over 5m // invalid variable name
  • $user 1h // missing keyword

Fenêtre coulissante

Par défaut, les règles YARA-L 2.0 sont évaluées à l'aide de fenêtres de saut. Une plage de données d'événements d'entreprise est divisée en un ensemble de fenêtres de saut qui se chevauchent, et chacune d'elles correspond à la durée spécifiée dans la section match. Les événements sont ensuite corrélés dans chaque fenêtre de saut. Avec les fenêtres de saut, il est impossible de rechercher des événements qui se produisent dans un ordre spécifique (par exemple, e1 se produisent jusqu'à deux minutes après e2). Une occurrence de l'événement e1 et une occurrence de l'événement e2 sont corrélées tant qu'elles se situent dans la fenêtre de saut.

Les règles peuvent également être évaluées à l'aide de fenêtres coulissantes. Avec les fenêtres glissantes, celles qui atteignent la durée spécifiée dans la section match sont générées au début ou à la fin par une variable d'événement de tableau croisé dynamique spécifiée. Les événements sont ensuite corrélés dans chaque fenêtre glissante. Cela permet de rechercher des événements qui se produisent dans un ordre spécifique (par exemple, e1 se produisent dans les deux minutes qui suivent e2). Une occurrence de l'événement e1 et une occurrence de l'événement e2 sont corrélées si l'événement e1 se produit pendant la période de glissement après l'événement e2.

Spécifiez des fenêtres coulissantes dans la section match d'une règle, comme suit:

<match-var-1>, <match-var-2>, ... over <duration> before|after <pivot-event-var>

La variable d'événement de tableau croisé dynamique est la variable d'événement sur laquelle les fenêtres coulissantes sont basées. Si vous utilisez le mot clé before, des fenêtres glissantes sont générées et se terminent par chaque occurrence de l'événement de tableau croisé dynamique. Si le mot clé after est utilisé, des fenêtres coulissantes sont générées à chaque occurrence de l'événement de tableau croisé dynamique.

Voici des exemples d'utilisations valides des fenêtres coulissantes:

  • $var1, $var2 over 5m after $e1
  • $user over 1h before $e2

Syntaxe de la section des résultats

Dans la section outcome, vous pouvez définir jusqu'à 10 variables de résultat, avec des noms arbitraires. Ces résultats seront stockés dans les détections générées par la règle. Chaque détection peut avoir des valeurs différentes pour les résultats.

Le nom du résultat, $risk_score, est spécial. Vous pouvez éventuellement définir un résultat portant ce nom. Si vous le faites, il doit s'agir d'un type entier. S'il est renseigné, risk_score s'affichera dans la vue Enterprise Insights pour les alertes provenant de la détection de règles.

Types de données de variables de résultat

Chaque variable de résultat peut avoir un type de données différent, déterminé par l'expression utilisée pour le calculer. Nous acceptons les types de données de résultat suivants:

  • integer
  • chaîne
  • listes d'entiers
  • listes de chaînes

Logique conditionnelle

Vous pouvez utiliser la logique conditionnelle pour calculer la valeur d'un résultat. Les conditions sont spécifiées à l'aide du modèle de syntaxe suivant:

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

Vous pouvez lire une expression conditionnelle en tant que "si BOOL_CLAUSE est vrai, puis renvoyer THEN_CLAUSE. Sinon, vous pouvez renvoyer ELSE_CLAUSE".

BOOL_CLAUSE doit renvoyer une valeur booléenne. Une expression BOOL_CLAUSE est semblable à une expression dans la section events. Elle peut par exemple contenir les éléments suivants:

  • Noms de champs UDM avec opérateur de comparaison. Exemple:

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

  • variable d'espace réservé définie dans la section events, par exemple:

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

  • qui renvoient une valeur booléenne, par exemple:

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

  • effectuez une recherche dans une liste de référence, par exemple:

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

THEN_CLAUSE et ELSE_CLAUSE doivent être du même type. Nous acceptons les nombres entiers et les chaînes.

Vous pouvez omettre ELSE_CLAUSE si le type de données est un entier. En cas d'omission, ELSE_CLAUSE prend la valeur 0. Exemple :

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

Vous devez indiquer la valeur ELSE_CLAUSE si le type de données est une chaîne.

Opérations mathématiques

Vous pouvez utiliser des opérations mathématiques pour calculer des résultats de type entiers. Nous acceptons l'addition et la soustraction (mais pas la multiplication, la division ni le modulo). Exemple :

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

Variables d'espace réservé dans les résultats

Lors du calcul des variables de résultat, vous pouvez utiliser les variables d'espace réservé définies dans la section des événements de votre règle. Dans cet exemple, supposons que $email_sent_bytes a été défini dans la section des événements de la règle:

Exemple d'événement unique:

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

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

Exemple avec plusieurs événements:

match:
  // This is a multi event rule 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
    + $email_sent_bytes
    + $file_event.principal.file.size
  )

condition:
  $email_event and $file_event

Agrégations

La section des résultats peut être utilisée dans les règles relatives à plusieurs événements (règles contenant une section de correspondance) et dans les règles relatives à un seul événement (règles qui ne contiennent pas de section de correspondance). Les exigences pour les agrégations sont les suivantes:

  • Règles multi-événements (avec section de correspondance)

    • L'expression permettant de calculer les résultats est évaluée sur tous les événements ayant généré une détection particulière.
    • L'expression doit être encapsulée dans une fonction d'agrégation.
      • Exemple : $max_email_size = max($e.network.sent_bytes)
      • Si l'expression contient un champ répété, l'agrégation s'applique à tous les éléments du champ répété, sur tous les événements ayant généré la détection.
  • Règles pour un seul événement (sans section de correspondance)

    • L'expression permettant de calculer les résultats est évaluée sur l'événement unique qui a généré une détection particulière.
    • Vous devez utiliser la fonction d'agrégation pour les expressions impliquant au moins un champ répété
      • Exemple : $suspicious_ips = array($e.principal.ip)
      • L'agrégation s'applique à tous les éléments du champ répété
    • Impossible d'utiliser la fonction d'agrégation pour les expressions n'impliquant pas de champ répété
      • Exemple : $threat_status = if($e.principal.file.size > 1024, "SEVERE", "MODERATE")

Vous pouvez utiliser les fonctions d'agrégation suivantes:

  • max(): génère la valeur maximale pour toutes les valeurs possibles. Fonctionne uniquement avec des nombres entiers.
  • min() : génère le minimum par rapport à toutes les valeurs possibles. Fonctionne uniquement avec des nombres entiers.
  • sum(): renvoie la somme de toutes les valeurs possibles. Fonctionne uniquement avec des nombres entiers.
  • count_distinct(): collecte toutes les valeurs possibles, puis génère le nombre distinct de valeurs possibles.
  • count(): se comporte comme count_distinct(), mais renvoie un nombre non distinct de valeurs possibles.
  • array_distinct() : collecte toutes les valeurs possibles, puis génère une liste de ces valeurs. La liste de valeurs est tronquée jusqu'à 25 éléments aléatoires.
  • array() : se comporte comme array_distinct(), mais renvoie une liste de valeurs non distinctes. Il tronque également la liste de valeurs à 25 éléments aléatoires.

La fonction d'agrégation est importante lorsqu'une règle inclut une section condition spécifiant que plusieurs événements doivent exister, car la fonction d'agrégation fonctionnera sur tous les événements ayant généré la détection.

Par exemple, si vos sections outcome et condition contiennent:

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

Étant donné que la section des conditions requiert plusieurs event pour chaque détection, les fonctions d'agrégation fonctionnent sur plusieurs événements. Supposons que les événements suivants ont généré une détection:

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

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

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

Les valeurs de vos résultats seront alors les suivantes:

  • $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"]

Points à retenir lors de l'utilisation de la section "Résultats" :

Autres remarques et restrictions:

  • La section outcome ne peut pas référencer une nouvelle variable d'espace réservé qui n'était pas déjà définie dans la section events.
  • La section outcome ne peut pas utiliser de variables d'événement qui n'ont pas été définies dans la section events.
  • La section outcome peut utiliser un champ d'événement qui n'a pas été utilisé dans la section events, car la variable d'événement à laquelle le champ d'événement appartient a déjà été définie dans la section events.
  • La section outcome ne peut mettre en corrélation que les variables d'événements déjà mises en corrélation dans la section events. Des corrélations se produisent lorsque deux champs d'événement de variables d'événements différentes sont équivalents.

Vous trouverez un exemple dans la section sur les résultats de la Présentation de YARA-L 2.0. Pour en savoir plus sur la détection des doublons dans la section sur les résultats, consultez Créer des analyses contextuelles.

Syntaxe de la section de condition

Dans la section condition, vous pouvez:

  • Spécifiez une condition de correspondance pour les événements et les espaces réservés définis dans la section events. Pour en savoir plus, consultez la section Événement et espace réservé d'espace réservé ci-dessous.
  • (Facultatif) Utilisez le mot clé and pour spécifier une condition de correspondance à l'aide de variables de résultat définies dans la section outcome. Pour en savoir plus, consultez la section Résultats conditionnels ci-dessous.

Les formats de condition suivants sont valides:

condition:
  <event/placeholder conditionals>
condition:
  <event/placeholder conditionals> and <outcome conditionals>

Expressions conditionnelles et d'événement

Indiquez ici les prédicats de condition pour les événements et les variables dans l'espace réservé, associés au mot clé and ou or.

Les conditions suivantes sont des conditions de délimitation. Ils forcent l'existence de la variable d'événement associée, ce qui signifie qu'au moins une occurrence de l'événement doit apparaître dans toute détection.

  • $var // equivalent to #var > 0
  • #var > n // where n >= 0
  • #var >= m // where m > 0

Les conditions suivantes sont non liées. Elles empêchent la variable d'événement associée d'exister. Il est donc possible qu'aucune occurrence de cet événement n'apparaisse dans une détection. Cela permet de créer des règles inexistantes, qui recherchent l'absence de variable au lieu de la présence d'une variable.

  • !$var // equivalent to #var = 0
  • #var >= 0
  • #var < n // where n > 0
  • #var <= m // where m >= 0

Dans l'exemple suivant, le caractère spécial # d'une variable (variable d'événement ou espace réservé) représente le nombre d'événements ou de valeurs distincts de cette variable.

$e and #port > 50 or #event1 > 2 or #event2 > 1 or #event3 > 0

L'exemple d'absence suivant est également valide et renvoie la valeur "true" s'il existe plus de deux événements distincts de $event1 et aucun événement distinct de $event2.

#event1 > 2 and !$event2

Voici des exemples de prédicats non valides:

  • $e, #port > 50 // incorrect keyword usage
  • $e or #port < 50 // or keyword not supported with non-bounding conditions
  • not $e // not keyword is not allowed for event and placeholder conditions

Expressions conditionnelles de résultat

Indiquez les prédicats de condition pour les variables de résultat ici, associés au mot clé and ou or, ou précédés du mot clé not.

Spécifiez les conditions de résultat différemment selon le type de la variable du résultat:

  • integer : comparez un littéral entier avec les opérateurs =, >, >=, <, <=, !=. Exemple:

    $risk_score > 10

  • string : comparez les données à un littéral de chaîne avec = ou !=, par exemple:

    $severity = "HIGH"

  • liste d'entiers ou de tableaux : spécifiez une condition à l'aide de la fonction arrays.contains. Exemple:

    arrays.contains($event_ids, "id_1234")

Classification des règles

Spécifier un résultat conditionnel dans une règle comportant une section de correspondance signifie que la règle sera classée comme une règle multi-événements pour le quota de règles. Pour en savoir plus sur la classification d'un seul et de plusieurs événements, consultez les articles relatifs à la règle d'un seul événement et à la règle appliquée à plusieurs événements.

Nombre (#)

Le caractère # est un caractère spécial dans la section condition. Si elle est utilisée avant un nom de variable d'événement ou d'espace réservé, elle représente le nombre d'événements ou de valeurs distincts qui remplissent toutes les conditions de la section events.

Valeur ($)

Le caractère $ est un autre caractère spécial de la section condition. Si elle est utilisée avant un nom de variable de résultat, elle représente la valeur de ce résultat.

Si vous l'utilisez avant un nom d'événement ou de variable d'espace réservé (par exemple, $event), il s'agit d'une version abrégée de #event > 0.

Syntaxe de la section "Options"

Dans la section options, vous pouvez spécifier les options de la règle. La syntaxe de la section options est semblable à celle de la section meta. Toutefois, la clé doit correspondre à l'un des noms d'options prédéfinis, et la valeur n'est pas limitée au type de chaîne.

Actuellement, la seule option disponible est allow_zero_values.

  • allow_zero_value : si ce champ est défini sur"true", les correspondances générées par la règle peuvent avoir des valeurs nulles comme variables de correspondance. Aucune valeur n'est indiquée dans les champs d'événement. Cette option est définie par défaut sur "false".

Voici la ligne de section options valide:

  • allow_zero_values = true

Vérification du type

Chronicle effectue une vérification du type en fonction de votre syntaxe YARA-L lorsque vous créez des règles dans l'interface. Les erreurs de vérification du type affichées vous aident à modifier la règle de sorte qu'elle fonctionne comme prévu.

Voici des exemples de prédicats non valides:

// $e.target.port is of type integer which cannot be compared to a string.
$e.target.port = "80"

// "LOGIN" is not a valid event_type enum value.
$e.metadata.event_type = "LOGIN"