Expressions, opérateurs et autres constructions
Ce document contient des informations qui vous aideront à créer des règles et des requêtes YARA-L à l'aide d'expressions.
Expressions booléennes
Les expressions booléennes sont des expressions de type booléen, qui incluent les expressions de comparaison, les expressions de fonction et les expressions de liste de référence ou de tableau de données. Vous pouvez utiliser des expressions booléennes dans les sections events et outcome d'une règle ou d'une requête YARA-L.
Expressions de comparaison
Les expressions de comparaison sont des expressions qui appliquent un opérateur de comparaison à deux expressions. Les expressions peuvent être des champs d'événement, des variables, des littéraux ou des expressions de fonction.
Exemple : expressions de comparaison
$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")
Expressions de fonction
Certaines expressions de fonction renvoient une valeur booléenne, qui peut être utilisée comme prédicat individuel dans la section events, par exemple :
re.regex()
net.ip_in_range_cidr()
Exemple : Expressions de fonction
re.regex($e.principal.hostname, `.*\.google\.com`)
net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")
Liste de référence ou tableau de données
Vous pouvez utiliser des listes de référence ou des tableaux de données dans les sections events ou outcome. Pour en savoir plus sur le comportement et la syntaxe des listes de référence et des tableaux de données, consultez Listes de référence et Utiliser des tableaux de données.
Exemple : Syntaxe pour les listes de référence
Les exemples suivants montrent la syntaxe de différents types de listes de références dans une requête :
// 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
Exemple : Syntaxe pour les tableaux de données
// STRING data table $e.target.hostname in %data_table_name.column_name // REGEX data table $e.target.hostname in regex %regex_table_name.column_name // CIDR data table $e.principal.ip in cidr %cidr_table_name.column_name
Exemple : Utiliser not et nocase dans la syntaxe des listes de références
// Exclude events whose hostnames match substrings in my_regex_list. not $e.principal.hostname in regex %my_regex_list // Event hostnames must match at least 1 string in my_string_list (case insensitive). $e.principal.hostname in %my_string_list nocase
L'opérateur nocase est compatible avec les listes STRING et REGEX.
Pour des raisons de performances, l'utilisation des listes de référence et des tableaux de données est soumise aux limites suivantes :
- Nombre maximal d'instructions
indans une requête, avec ou sans opérateurs spéciaux : 7 - Nombre maximal d'instructions
inavec l'opérateurregex: 4 - Nombre maximal d'instructions
inavec l'opérateurcidr: 2
Expressions logiques
Vous pouvez utiliser les opérateurs logiques and et or dans la section events.
Exemple : Expressions logiques
$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é (du plus élevé au plus bas) est not, and, or. Par exemple, "a or b and c" est évalué comme "a or (b and c)" lorsque les opérateurs or et and sont définis explicitement dans l'expression.
Dans la section events, les prédicats sont joints à l'aide de l'opérateur and si aucun opérateur n'est défini de manière explicite. L'ordre d'évaluation peut être différent si l'opérateur and est implicite dans l'expression.
Prenons les expressions de comparaison suivantes, où or est défini de manière explicite et où l'opérateur and est implicite.
$e1.field = "bat" or $e1.field = "baz" $e2.field = "bar"
Elle est interprétée comme suit :
($e1.field = "bat" or $e1.field = "baz") and ($e2.field = "bar")
Comme or est défini de manière explicite, les prédicats environnants sont regroupés et évalués en premier. Le dernier prédicat, $e2.field = "bar". est joint de manière implicite à l'aide de and. L'ordre d'évaluation est donc modifié.
Types énumérés
Vous pouvez utiliser les opérateurs avec des types énumérés. Il peut être appliqué aux règles pour simplifier et optimiser les performances (utiliser 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. La règle recherchera donc tous les événements listés :
$e.metadata.event_type >= "USER_CATEGORIZED" and $e.metadata.event_type <= "USER_RESOURCE_DELETION"
Modificateur "Nocase"
Pour ignorer la casse dans une expression de comparaison entre des valeurs de chaîne ou une expression régulière, ajoutez nocase à la fin de l'expression, comme illustré dans les exemples suivants.
Exemple : modificateur nocase
$e.principal.hostname != "http-server" nocase
$e1.principal.hostname = $e2.target.hostname nocase
$e.principal.hostname = /dns-server-[0-9]+/ nocase
re.regex($e.target.hostname, `client-[0-9]+`) nocase
Le modificateur nocase ne peut pas être utilisé lorsque le type de champ est une valeur énumérée. Les exemples suivants ne sont pas valides et généreront des erreurs de compilation :
$e.metadata.event_type = "NETWORK_DNS" nocase
$e.network.ip_protocol = "TCP" nocase
Commentaires
Vous pouvez utiliser des commentaires dans les requêtes pour fournir plus d'informations. Vous utilisez la barre oblique pour indiquer un commentaire :
- Pour un commentaire sur une seule ligne, utilisez deux barres obliques (
// comment). - Pour un commentaire sur plusieurs lignes, utilisez la barre oblique et l'astérisque (
/* comment */).
Littéraux
YARA-L accepte les littéraux entiers et flottants non négatifs, ainsi que les littéraux de chaîne, booléens et d'expression régulière. Les littéraux sont des valeurs fixes utilisées dans les conditions de requête. YARA-L utilise également d'autres constructions de type littéral, telles que des expressions régulières (entre barres obliques) pour la mise en correspondance de modèles et des valeurs booléennes (true/false) pour la logique.
Littéraux de chaîne
Les littéraux de chaîne sont des séquences de caractères placés entre guillemets doubles (") ou guillemets inversés (`). La chaîne est interprétée différemment selon le type de guillemet utilisé :
- Guillemets doubles ("hello\tworld") : à utiliser pour les chaînes normales. Les caractères d'échappement doivent être inclus, où \t est interprété comme une tabulation.
- Guillemets inversés (`hello\tworld`) : à utiliser lorsque tous les caractères doivent être interprétés littéralement, où \t n'est pas interprété comme une tabulation.
Littéraux d'expression régulière
Pour les littéraux d'expression régulière, vous avez deux options :
Si vous souhaitez utiliser des expressions régulières directement sans la fonction
re.regex(), utilisez/regex/pour les littéraux d'expression régulière.Si vous souhaitez utiliser des littéraux de chaîne comme littéraux d'expression régulière, utilisez la fonction
re.regex(). Notez que pour les littéraux de chaîne à guillemets doubles, vous devez échapper les barres obliques inverses avec des barres obliques inverses, ce qui peut sembler étrange.
Les exemples suivants montrent des expressions régulières équivalentes :
re.regex($e.network.email.from, `.*altostrat\.com`)
re.regex($e.network.email.from, ".*altostrat\\.com")
$e.network.email.from = /.*altostrat\.com/
Google recommande d'utiliser des guillemets inversés pour les chaînes dans les expressions régulières afin de faciliter la lecture.
Opérateurs
| 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, toutes les variables utilisent la syntaxe $<variable name>. Les types de variables suivants peuvent être utilisés dans YARA-L.
Variables d'événement
Les variables d'événement représentent des groupes d'événements ou des événements d'entité. Vous spécifiez des conditions pour les variables d'événement dans la section events à l'aide d'un nom, d'une source d'événement et de champs d'événement.
Les sources d'événements sont
udm(pour les événements normalisés) etgraph(pour les événements d'entité). Si la source est omise,udmest définie comme source par défaut.Les champs d'événement sont représentés sous la forme d'une chaîne .<nom de champ> (par exemple, $e.field1.field2). Les chaînes de champs commencent toujours à partir de la source de premier niveau (UDM ou entité).
Variables de correspondance
Les variables de correspondance sont utilisées dans la section match pour regrouper les événements en fonction de valeurs communes dans une période spécifiée.
Ils 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 période). Lorsque la requête trouve une correspondance, les valeurs des variables de correspondance sont renvoyées.
Vous spécifiez ce que représente chaque variable de correspondance dans la section events.
Variables d'espace réservé
Les variables d'espace réservé permettent de capturer et de stocker des valeurs spécifiques à partir des champs d'événement UDM, qui peuvent ensuite être référencées et utilisées dans une requête. Ils permettent d'associer des événements disparates, en particulier dans les requêtes multi-événements. En attribuant une valeur commune (par exemple, userid ou hostname) à un espace réservé, vous pouvez ensuite utiliser cet espace réservé dans la section match pour regrouper les événements qui partagent cette valeur dans une période spécifiée.
Vous définissez des variables d'espace réservé dans la section events en attribuant la valeur d'un champ UDM à un nom de variable précédé d'un $ (par exemple, $targetUser = $e.target.user.userid).
Vous pouvez également définir des variables d'espace réservé dans les sections suivantes :
- Section
conditionpour spécifier les conditions de correspondance. - section
outcomepour effectuer des calculs, définir des métriques ou extraire des points de données spécifiques des événements correspondants. matchpour regrouper les événements par valeurs communes.
Mots clés
Dans YARA-L, les mots clés sont des mots réservés qui définissent la structure et la logique d'une requête de détection. Elles permettent de spécifier différentes sections d'une requête, d'effectuer des opérations logiques et mathématiques, et de définir des conditions pour les événements correspondants. Ces mots clés ne peuvent pas être utilisés comme identifiants pour les requêtes, les chaînes ou les variables.
Les mots clés ne sont pas sensibles à la casse (par exemple, and et AND sont équivalents).
Principales catégories de mots clés YARA-L 2.0
Cette liste n'est pas exhaustive, mais elle couvre les principaux mots clés utilisés dans YARA-L 2.0 pour créer des requêtes de détection robustes.
- Définition de la requête :
rule: lance la définition d'une nouvelle requête YARA-L.private: désigne une requête comme privée, ce qui l'empêche d'être directement exposée ou déclenchée en externe.global: marque une requête comme globale, indiquant qu'elle doit être appliquée de manière générale.
- Sections de la requête :
meta: introduit la section des métadonnées pour obtenir des informations descriptives sur la requête.strings: indique la section où les modèles de chaîne sont définis.condition: spécifie la section contenant la logique booléenne pour le déclenchement des requêtes.events: définit la section permettant de spécifier les variables d'événement et leurs conditions.match: présente la section permettant d'agréger les valeurs sur une période.outcome: définit la section permettant d'ajouter du contexte et d'attribuer un score aux requêtes déclenchées.
- Modificateurs de chaîne :
ascii: indique qu'une chaîne doit correspondre à du texte ASCII.wide: indique qu'une chaîne doit correspondre à des caractères larges (UTF-16).nocase: effectue une mise en correspondance de chaînes non sensible à la casse.fullword: exige que la chaîne corresponde à un mot entier.xor: applique la transformation XOR à la chaîne avant la mise en correspondance.base64,base64wide: applique l'encodage Base64 avant la correspondance.
- Opérateurs logiques :
and,or,not: opérateurs logiques booléens standards pour combiner des conditions.all of,any of: utilisé pour évaluer plusieurs expressions dans une condition.
- Opérateurs de comparaison et relationnels :
at: spécifie un décalage exact pour la correspondance de chaîne.contains: vérifie si une chaîne contient une sous-chaîne.startswith,endswith: vérifie si une chaîne commence ou se termine par une sous-chaîne.icontains,istartswith,iendswith,iequals: versions insensibles à la casse.matches: utilisé pour la correspondance des expressions régulières.
- Types de données et spécificateurs de taille :
int8,uint8,int16,uint16,int32,uint32: types entiers avec des tailles spécifiées.int8be,uint8be,int16be,uint16be,int32be,uint32be: versions big-endian des types entiers.filesize: représente la taille du fichier analysé.entrypoint: fait référence au point d'entrée d'un exécutable.
Maps
YARA-L est compatible avec les cartes pour les types de données Struct et Label, qui sont utilisés dans certains champs UDM.
Pour rechercher une paire clé-valeur spécifique dans les types de données Struct et Label, utilisez la syntaxe de carte standard :
- Syntaxe des champs de structure :
$e.udm.additional.fields["pod_name"] = "kube-scheduler" - Syntaxe du champ de libellé :
$e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"
Exemple : Utilisation valide et non valide des cartes
Les exemples suivants montrent une utilisation valide et non valide des cartes.
Utilisation valide des cartes
Utiliser un champ Struct dans la section "Événements" :
events: $e.udm.additional.fields["pod_name"] = "kube-scheduler"
Utiliser un champ "Libellé" dans la section "Résultat" :
outcome: $value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])
Attribuer une valeur de carte à un espace réservé :
$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]
Utiliser un champ de carte 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"]
Utilisation non acceptée des cartes
Combiner des mots clés any ou all avec une carte
all $e.udm.additional.fields["pod_name"] = "kube-scheduler"
Autres types de valeurs
La syntaxe Map ne peut renvoyer qu'une valeur de chaîne. Dans le cas des types de données [Struct](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#struct), la syntaxe de la carte ne peut accéder qu'aux clés dont les valeurs sont des chaînes. Il n'est pas possible d'accéder aux clés dont les valeurs sont d'autres types primitifs, comme les entiers.
Gestion des valeurs en double dans les cartes
L'accès à la carte est destiné à récupérer une seule valeur associée à une clé spécifique. Il s'agit d'un comportement standard et attendu.
Toutefois, dans de rares cas, le contexte de map access peut involontairement pointer vers plusieurs valeurs. Dans le cas rare où l'accès à la carte fait référence à plusieurs valeurs, map access renvoie de manière déterministe la première valeur. Cela peut se produire si un libellé comporte une clé en double ou un champ répété ancêtre.
L'étiquette comporte une clé en double
La structure des libellés représente une carte, mais n'impose pas l'unicité des clés. Par convention, une carte doit comporter des clés uniques. Google SecOps ne recommande donc pas de remplir un libellé avec des clés en double.
Exemple : libellé avec clé en double
Le texte de la requête $e.metadata.ingestion_labels["dupe-key"] renverrait la première valeur possible, val1, s'il était exécuté sur l'exemple de données suivant :
// Disrecommended usage of label with a duplicate key:
event {
metadata{
ingestion_labels{
key: "dupe-key"
value: "val1" // This is the first possible value for "dupe-key"
}
ingestion_labels{
key: "dupe-key"
value: "val2"
}
}
}
Le libellé comporte un champ répété ancêtre
Un champ répété peut contenir un libellé en tant que champ enfant. Deux entrées différentes dans le champ répété de premier niveau peuvent contenir des libellés ayant la même clé.
Exemple : libellé avec un champ répété ancêtre
Le texte de la requête $e.security_result.rule_labels["key"] renverrait la première valeur possible, "val3", s'il était exécuté sur l'exemple de données suivant :
event {
// security_result is a repeated field.
security_result {
threat_name: "threat1"
rule_labels {
key: "key"
value: "val3" // This is the first possible value for "key"
}
}
security_result {
threat_name: "threat2"
rule_labels {
key: "key"
value: "val4"
}
}
}
Accéder aux variables de résultat dans les cartes
Cette section explique comment accéder aux variables de résultat dans les cartes en tant que types de données d'origine (par exemple, des entiers, des booléens ou des listes de ces types) plutôt que des chaînes. Vous pouvez utiliser cette fonctionnalité pour plus de flexibilité et de précision dans la logique de vos requêtes.
Les données sur les résultats sont disponibles dans les champs suivants :
- Les valeurs de résultat conservent leurs types d'origine dans le champ
variables. - Le champ
outcomesstocke les versionsstringpour assurer la rétrocompatibilité.
Vous pouvez accéder à ces valeurs de résultat à l'aide de la carte variables pour récupérer le type spécifique ou accéder aux éléments d'une séquence à l'aide de l'indexation de tableau. Vous pouvez accéder à un élément spécifique de la séquence par son index ou sélectionner l'intégralité de la séquence pour évaluer chaque valeur individuellement.
Syntaxe :
$d.detection.detection.variables[OUTCOME_NAME].TYPE_SUFFIX
Syntaxe pour les séquences :
$d.detection.detection.variables[OUTCOME_NAME].SEQUENCE_TYPE_SUFFIX.TYPE_VALS_SUFFIX
Exemples : accéder aux variables de résultat dans les cartes
Accéder à un résultat de chaîne :
$my_string_outcome = $d.detection.detection.variables["outcome_ip"].string_val
Cet exemple récupère directement la valeur de la chaîne (par exemple, "1.1.1.1" si outcome_ip était une chaîne unique).
Accéder à un résultat entier
$my_int_outcome = $d.detection.detection.variables["outcome_port"].int64_value
Cet exemple récupère la valeur entière (par exemple, 30).
Accéder à une liste d'entiers à l'aide d'Int64Sequence
$my_int_list = $d.detection.detection.variables["outcome_ports"].int64_seq.int64_vals
Cet exemple récupère la liste complète des entiers et les supprime comme des champs répétés (par exemple, [2, 3, 4]).
Accéder à un élément spécifique d'une liste d'entiers
$first_int = $d.detection.detection.variables["outcome_ports"].int64_seq.int64_vals[0]
Cet exemple récupère le premier nombre entier de la liste (par exemple, 2).
Accéder à une liste de chaînes (StringSequence)
$my_string_list = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals
Cet exemple récupère la liste complète des chaînes et les annule comme des champs répétés (par exemple, ["1.1.1.1", "2.2.2.2"]).
Accéder à un élément spécifique d'une liste de chaînes
$first_ip = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals[0]
Cet exemple récupère la première adresse IP de la liste (par exemple, "1.1.1.1").
Suffixes de type disponibles pour variables
Pour obtenir la liste complète des suffixes acceptés, consultez FindingVariable.
Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.