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 de variable, les définitions et les utilisations dans l'ordre suivant:

  1. méta
  2. events
  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 les commentaires contenant deux barres obliques (// comment) ou les commentaires multilignes définis à l'aide des barres obliques (/* comment */), comme vous le feriez dans C.

Constantes

Les constantes de type "entier", "chaîne", "booléen" et d'expression régulière sont acceptées.

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

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

  1. Guillemets doubles (") : à 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 inversés (`) : permettent d'interpréter tous les caractères littéralement.
    Par exemple, "hello\tworld" : Hcacbbbc n'est pas interprété comme un onglet.

Pour les expressions régulières, deux options s'offrent à vous.

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

Vous pouvez également utiliser des constantes de chaîne en tant que constantes d'expression régulière lorsque vous utilisez la fonction re.regex(). Notez que pour les constantes de chaîne de guillemets doubles, vous devez échapper les barres obliques inverses avec 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 des expressions régulières.

Opérateurs

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

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

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énements : représentent des groupes d'événements au format normalisé (UDM) ou des événements d'entité. Spécifiez les conditions des variables d'événements dans la section events. Vous identifiez les variables d'événements à l'aide de champs "Nom", "Source et é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 la source par défaut. Les champs d'événements sont représentés par une chaîne de .<field name> (par exemple, $e.field1.field2). Les chaînes de champs d'événement commencent toujours par la source racine (UDM ou Entity).

  • Variables de correspondance : déclarez dans la section match Les variables de correspondance deviennent des champs de groupe pour la requête, car une ligne est renvoyée pour chaque ensemble unique de variables de correspondance (et pour chaque période). 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 d'espace réservé sont semblables aux variables de correspondance. Cependant, vous pouvez utiliser des variables dans la section condition pour spécifier des conditions de correspondance.

Utilisez des variables de correspondance et des variables d'espace réservé pour déclarer des relations entre les champs d'événement via des conditions de jointure transitives (voir Syntaxe de la section "Événements" pour plus d'informations).

Fonctions

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

Vous pouvez utiliser ces fonctions dans les zones suivantes 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(encodedString)

Les sections suivantes décrivent comment les utiliser.

Concaténer des chaînes ou des entiers

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

strings.concat(a, b)

Cette fonction prend deux arguments, qui peuvent être des chaînes ou des entiers, et renvoie les deux valeurs concaténées en tant que chaîne. Les entiers sont castés sur une 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 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 entière comme arguments. main.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 principal.port à partir de l'événement $e1, avec "principal.hostname" à partir de l'événement $e2. Il renverra une erreur de compilation, 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 la chaîne en majuscules ou en minuscules

Ces fonctions renvoient du texte de chaîne après avoir modifié 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 en tant qu'argument. Si la valeur 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 "main.domain.name" est "dGVzdA=Httpquot;, qui est l'encodage base64 de la chaîne "test".

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

Fonctions d'expression régulière

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

  • re.expressions(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 une correspondance d'expression régulière dans YARA-L 2.0 en utilisant 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 prenant les paramètres suivants :
    • Champ auquel l'expression régulière est appliquée.
    • Expression régulière spécifiée en tant que 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 lors de la définition 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 qui correspond à 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 établir une correspondance avec la chaîne exacte ou uniquement avec 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 mise en correspondance complète des champs UDM, ajoutez un (?s) à l'expression régulière. Par exemple, remplacez /.*allUDM.*/ par /(?s).*allUDM.*/.

Capture d'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 utilise deux arguments:

  • string: chaîne d'origine dans laquelle effectuer la recherche.
  • expression régulière: expression régulière indiquant le modèle à rechercher.

L'expression régulière peut contenir zéro ou un groupe de capture entre parenthèses. Si l'expression régulière contient 0 groupe de captures, la fonction renvoie la première sous-chaîne correspondante. Si l'expression régulière contient un groupe de captures, 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 compilation.

Dans cet exemple, si $e.principal.hostname contient "aaa1bbaa2" les valeurs suivantes sont vraies, 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 capture tout ce qui suit le symbole @ dans un e-mail. Si le champ $e.network.email.from est défini sur test@google.com, l'exemple renvoie google.com. L'exemple contient un groupe de capture.

"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 utilise trois arguments:

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

Renvoie une nouvelle chaîne dérivée de la chaîne de texte d'origine, où toutes les sous-chaînes qui correspondent au modèle de replaceRegex sont remplacées par la valeur de "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 au 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é au premier occurrence trouvée. Par exemple, re.replace("ana", "ana","111") renvoie la chaîne "b111na".

Cet exemple capture tout ce qui suit le symbole @ dans un e-mail, remplace com par org, puis renvoie le résultat. Notez l'utilisation des 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"
                     )

Fonctions de date

Chronicle est compatible avec les fonctions de 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 comme argument unix_secondes. Les entiers négatifs représentent les heures antérieures à l'époque Unix. Si vous fournissez un entier non valide, par exemple une valeur qui entraîne un dépassement, la fonction renvoie -1. Ce scénario n'est pas courant.

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

0 > timestamp.get_hour(123)

Extraction de données temporelles

Renvoie un nombre entier compris entre 0 et 59.

timestamp.get_minute(unix_seconds [, time_zone])

La fonction suivante renvoie un entier compris entre 0 et 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] représentant le jour de la semaine commençant par dimanche. Par exemple, 1 = dimanche, 2 = lundi, etc.

timestamp.get_day_of_week(unix_seconds [, time_zone])

La fonction suivante renvoie un entier compris entre 0 et 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 données temporelles comportent les mêmes arguments.

  • unix_secondes 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.
  • Le paramètre "time_zone" est facultatif et correspond à une chaîne représentant un fuseau horaire. Si cette option est omise, la valeur par défaut est "GMT". Vous pouvez spécifier des fuseaux horaires à l'aide de littéraux de chaîne. Vous disposez des options suivantes :
    • Nom de la base de données TZ, par exemple "Amérique/Los_Angeles". Pour en savoir plus, consultez la colonne &quotTT Database Name" de cette page.
    • Décalage horaire par rapport à l'heure UTC, au format (+|-)H[H][:M[M]], par exemple: "-08:00".

Dans cet exemple, l'argument "time_zone" est omis. Par défaut, il est &&tt;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 des exemples d'autres spécificateurs de fuseau horaire valides que vous pouvez transmettre en tant que deuxième argument aux fonctions d'extraction de temps:

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

Horodatage actuel

Renvoie un nombre entier représentant l'heure actuelle en secondes Unix. Cette valeur est environ égale à l'horodatage de détection et dépend de l'exécution de la règle.

timestamp.current_seconds()

L'exemple suivant renvoie la valeur "True" si le certificat a expiré depuis plus de 24 heures. Elle calcule le décalage horaire 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 sont espacés de plus de cinq minutes, quel que soit l'événement qui est survenu en premier. Notez que l'exemple utilise des fonctions imbriquées.

5 < timestamp.get_minute(
      math.abs($e1.metadata.event_timestamp.seconds
               - $e2.metadata.event_timestamp.seconds
      )
    )

Fonctions Net

Affiche 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 sur 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 compatibles.

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 uniques et récurrents.

Exemple d'IPv4:

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

Exemple d'adresse IPv6:

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

Pour voir un exemple de règle à l'aide de l'instruction net.ip_in_range_cidr(), consultez l'exemple de règle. Un seul événement dans une plage d'adresses IP

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 entre guillemets, et une partie de valeur doit être une chaîne entre guillemets:

<key> = "<value>"

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

Syntaxe de la section "Événements"

Dans la section events, répertoriez les prédicats pour spécifier les éléments suivants:

  • Que représente chaque correspondance ou variable d'espace réservé ?
  • Expressions binaires simples en tant que conditions
  • Expressions fonction comme conditions
  • Expressions de liste 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 de correspondance peut représenter n'importe quelle valeur du tableau. Il est également possible d'attribuer plusieurs champs d'événement à une seule correspondance ou variable d'espace réservé. Il s'agit d'une condition de jointure transitive.

Par exemple, cette agrégation :

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

sont équivalents à:

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

Lors de l'utilisation d'une variable, celle-ci doit être déclarée via une déclaration. Une variable est considérée comme une erreur de compilation lorsqu'elle est utilisée sans déclaration.

Expressions binaires simples en tant que conditions

Pour créer une expression binaire simple à utiliser comme condition, utilisez la syntaxe suivante:

  • <EXPR> <OP> <EXPR>

L'expression peut être un champ d'événement, une variable, une constante 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.timestamp > $e2.metadata.timestamp
  • $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 constantes, cette erreur est considérée comme une compilation.

Expressions fonction comme conditions

Certaines expressions de fonction renvoient une valeur booléenne qui peut être utilisée en tant que 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 liste de référence en tant que conditions

Utilisez l'opérateur in pour vérifier l'existence de valeurs UDM dans une liste de référence basée sur l'égalité. L'opérateur in peut être associé à not pour exclure les valeurs d'une liste de référence. Le nom de la liste de référence doit être précédé du caractère %.

Actuellement, seules les valeurs de chaîne sont acceptées:

  • $e.principal.hostname in %hostname_list
  • $e.about.ip in %phishing_site_list
  • $hostname in %whitelisted_hosts

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, les ordres de priorité les plus élevés sont les suivants : not, and, or.

Par exemple, "a or b and c" est évalué comme "a or (b and c)". Vous pouvez utiliser des parenthèses pour modifier la priorité si nécessaire.

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

Modificateurs

nocase

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

  • $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 est une valeur énumérée. Les exemples ci-dessous sont incorrects et génèrent des erreurs de compilation:

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

Champs répétés

tout, tous

Dans UDM et l'Entity, certains champs sont libellés comme étant 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. En d'autres termes, si le champ répété est utilisé dans la règle, nous l'évaluons 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 correspondances, même si "1.2.3.4" et "5.6.7.8" sont tous les deux 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 du 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. Ces éléments ne peuvent pas non plus être utilisés lors de l'attribution d'un champ répété à une variable d'espace réservé ou lors de l'association d'un champ à 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 établir une correspondance ou rejoindre un champ répété, utilisez $e.principal.ip = $ip. Il y a une valeur de variable de correspondance ou une jointure pour chaque élément du champ répété.

Lors de l'écriture d'une condition avec any ou all, notez que l'annulation de la condition avec not peut ne pas 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", ce qui 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".

Syntaxe de la section de correspondance

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.
  • Spécifiez la période à utiliser pour mettre en corrélation les événements après le mot clé over. Les événements non inclus dans la période sont ignorés.
  • Spécifiez la période suivante à l'aide de la syntaxe suivante : <number><s/m/h/d> Lorsque s/m/h/d signifie respectivement les secondes, les minutes, les heures et les jours.
  • Vous pouvez spécifier une durée minimale d'une minute.
  • Vous pouvez spécifier une durée maximale 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 situés à plus de cinq minutes d'intervalle ne sont pas corrélés et sont donc ignorés par la règle.

Voici un autre exemple de match valide:

$user over 1h

Cette instruction renvoie $user lorsque la règle trouve une correspondance. La période spécifiée est d'une heure. Les événements situés à plus d'une heure d'intervalle ne sont pas corrélés. Elles ne sont pas considérées comme des détections.

Voici un autre exemple de 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. La période spécifiée est de deux minutes. Les événements situés à plus de deux minutes d'intervalle ne sont pas corrélés. Elles ne sont pas considérées comme des détections.

Les exemples suivants illustrent les 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 période de données d'événement d'entreprise est divisée en un ensemble de fenêtres de saut qui se chevauchent, chacune ayant la durée spécifiée dans la section match. Des événements sont ensuite mis en corrélation dans chaque fenêtre de saut. Avec les périodes de saut

Les règles peuvent aussi être évaluées à l'aide de fenêtres coulissantes. Avec les fenêtres coulissantes, les fenêtres coulissantes dont la durée est 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 au sein de chaque fenêtre glissante. Cela permet de rechercher des événements qui se produisent dans un ordre spécifique (par exemple, e1 se produit dans les deux minutes suivant e2) et une occurrence de e1 et e2 si l'événement e1 se produit pendant la période glissante après l'événement e2.

Spécifiez les fenêtres glissantes 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 glissantes sont basées. Si vous utilisez le mot clé before, des fenêtres glissantes sont générées, se terminant par chaque occurrence de l'événement de tableau croisé dynamique. Si le mot clé after est utilisé, des fenêtres glissantes sont générées à chaque occurrence de l'événement de tableau croisé dynamique.

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

  • $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. Les résultats peuvent varier en fonction des résultats.

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

Types de données des 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 schéma de syntaxe suivant:

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

Vous pouvez lire une expression conditionnelle en tant que &ift;si BOOL_CLAUSE est vraie, puis renvoyer THEN_CLAUSE. Sinon, renvoyer ELSE_CLAUSE".

La valeur BOOL_CLAUSE doit correspondre à une valeur booléenne. Une expression BOOL_CLAUSE se présente sous la forme d'expressions dans la section events. Par exemple, elle peut contenir les éléments suivants:

  • Noms de champs UDM avec l'opérateur de comparaison, par exemple:

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

  • variable d'espace réservé qui a été 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)

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

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

Les types de données THEN_CLAUSE et ELSE_CLAUSE doivent être identiques. Nous acceptons les chaînes entières.

Vous pouvez omettre la valeur ELSE_CLAUSE si le type de données est un entier. En cas d'omission, la valeur ELSE_CLAUSE est égale à 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 types de données sous forme d'entiers. Nous acceptons les ajouts et les soustractions. 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

Lorsque vous calculez des variables de résultat, vous pouvez utiliser les variables d'espace réservé qui ont été définies dans la section des événements de votre règle. Dans cet exemple, supposons que $email_sent_bytes ait été défini dans la section des événements de la règle:

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

L'expression permettant de calculer un résultat doit être encapsulée dans une fonction d'agrégation. Les fonctions d'agrégation fonctionnent sur tous les événements qui ont généré une détection particulière. Vous pouvez utiliser les fonctions d'agrégation suivantes:

  • max(): génère le maximum de valeurs possibles. Fonctionne uniquement avec les nombres entiers.
  • min(): renvoie le minimum de toutes les valeurs possibles. Fonctionne uniquement avec les nombres entiers.
  • sum() : génère la somme sur toutes les valeurs possibles. Fonctionne uniquement avec les 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. Il tronque la liste de valeurs à 25 éléments aléatoires.
  • array() : se comporte comme array_distinct(), mais renvoie une liste de valeurs non distincte. De plus, la liste des valeurs est tronquée à 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 être présents. En effet, la fonction d'agrégation fonctionnera sur tous les événements qui ont 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 de condition nécessite qu'il y ait plusieurs éléments event pour chaque détection, les fonctions d'agrégation fonctionnent sur plusieurs événements. Supposons que les événements suivants aient 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 sont ensuite:

  • $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 importants à connaître lors de l'utilisation de la section des résultats:

  • Vous ne pouvez utiliser que la section outcome dans les règles multi-événements, qui correspondent à des règles comportant une section match.
  • La section outcome ne peut pas inclure les événements qui n'ont pas été définis dans la section events. Vous ne pouvez mettre en corrélation que des événements déjà corrélés dans la section events. De même, vous ne pouvez pas définir une nouvelle variable d'espace réservé qui n'est pas déjà définie dans la section events.

Vous trouverez un exemple dans la section des résultats de la Présentation de YARA-L 2.0. Pour en savoir plus sur les problèmes de détection liés à la section des résultats, consultez également la page Créer une analyse contextuelle.

Syntaxe de la section de condition

Comptage

Le caractère # est un caractère spécial dans la section condition. Si elle est utilisée avant un nom d'événement ou de variable 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.

.

Syntaxe

Dans la section condition, spécifiez la condition de correspondance sur les événements et les variables définis dans la section events. Prédicats de correspondance de liste ici, associés au mot clé and ou or.

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

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

Les conditions suivantes ne sont pas liées. Ils permettent de faire en sorte que la variable d'événement associée n'existe pas. Il est donc possible qu'aucune occurrence de l'événement ne s'affiche dans une détection. Cela permet de définir des règles inexistantes, qui recherchent l'absence de variable au lieu 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 # sur une variable (la variable d'événement ou la variable d'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 inexistant suivant est également valide et évalué sur "true" s'il existe plus de deux événements distincts à partir de $event1 et qu'aucun événement distinct ne provient 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

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, une 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 cette règle est définie sur"True", les correspondances générées par la règle ne peuvent avoir aucune valeur en tant que valeurs de variable de correspondance. Aucune valeur n'est indiquée dans les champs d'événements lorsqu'ils ne sont pas renseignés. Par défaut, cette option est définie sur "False".

La ligne options suivante est valide:

  • allow_zero_values = true

Type

Chronicle effectue une vérification du type par rapport à votre syntaxe YARA-L lorsque vous créez des règles dans l'interface. Les erreurs de vérification du type affichées vous permettent de 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"