Limites et problèmes connus de YARA-L 2.0
Ce document s'adresse aux ingénieurs en détection qui souhaitent déboguer la logique des règles et optimiser l'exécution de YARA-L 2.0. Il explique comment gérer les comportements non standards du moteur, tels que l'annulation de l'imbrication des champs, l'expansion du produit cartésien dans les agrégations et la cohérence finale de l'enrichissement. En suivant ces méthodes, vous pouvez éviter les erreurs de logique qui entraînent des valeurs de résultat gonflées ou des détections manquées.
YARA-L 2.0 utilise un modèle d'exécution spécifique dans lequel les champs répétés sont développés en lignes d'événements individuelles lors de l'évaluation. Étant donné que cette transformation se produit au niveau du moteur, le référencement de plusieurs champs répétés ou l'exécution d'opérations arithmétiques sur des types UDM non signés nécessitent des solutions de contournement de syntaxe spécifiques pour éviter les erreurs de compilation ou les ensembles de résultats incorrects. Ce document décrit ces contraintes techniques et les schémas logiques requis pour les résoudre.
Avant de commencer
Avant de tester ou de modifier des règles YARA-L 2.0, assurez-vous que votre compte dispose des droits techniques suivants :
Rôles IAM requis
roles/chronicle.viewer(Lecteur Security Operations) : pour afficher les règles existantes et les métadonnées de détection.roles/chronicle.editor(Éditeur des opérations de sécurité) : pour modifier la logique des règles et enregistrer les modifications.
Autorisations requises
chronicle.rules.runTest: obligatoire pour exécuter la fonctionnalité Exécuter le test sur les données historiques.chronicle.detections.get: pour examiner la sortie des événements non imbriqués dans le tableau de bord des détections.
Terminologie clé
- UDM (Unified Data Model) : schéma normalisé utilisé pour structurer toutes les données de télémétrie de sécurité ingérées sur la plate-forme.
- Désimbrication : expansion au niveau du moteur d'un seul événement UDM contenant un champ répété (tableau) en plusieurs lignes. Chaque ligne représente un élément unique du tableau, ce qui peut entraîner une multiplication des lignes lors de l'évaluation des règles.
- T₀ (exécution initiale) : première exécution d'une règle sur les données de télémétrie entrantes. Cela se produit pendant la phase de "streaming", souvent avant la finalisation des processus d'enrichissement en arrière-plan (comme les ajustements GeoIP ou ASN).
Agrégations de résultats avec suppression de l'imbrication des champs répétés
Lorsqu'une règle fait référence à un champ répété dans une variable d'événement comportant plusieurs éléments, chaque élément est divisé en une ligne d'événement distincte.
Par exemple, les deux adresses IP du champ répété target.ip de l'événement $e sont divisées en deux instances de $e, chacune avec une valeur target.ip différente.
rule outbound_ip_per_app {
meta:
events:
$e.principal.application = $app
match:
$app over 10m
outcome:
$outbound_ip_count = count($e.target.ip) // yields 2.
condition:
$e
}
Enregistrements d'événements : avant et après l'annulation de l'imbrication
Les tableaux de cette section montrent comment un seul événement contenant un tableau d'adresses IP est transformé en deux enregistrements distincts.
Avant l'annulation de l'imbrication
Le tableau suivant montre l'enregistrement d'événement avant l'annulation de l'imbrication du champ répété :
| metadata.id | principal.application | target.ip |
|---|---|---|
aaaaaaaaa |
Google SecOps |
[192.0.2.20, 192.0.2.28] |
Après l'annulation de l'imbrication
Le tableau suivant montre l'enregistrement d'événement après l'annulation de l'imbrication du champ répété :
| metadata.id | principal.application | target.ip |
|---|---|---|
aaaaaaaaa |
Google SecOps |
192.0.2.20 |
aaaaaaaaa |
Google SecOps |
192.0.2.28 |
Champs imbriqués répétés (produit cartésien)
Lorsqu'une règle fait référence à un champ répété imbriqué dans un autre, comme security_results.action, la suppression de l'imbrication se produit simultanément aux deux niveaux (parent et enfant). Cela génère un produit cartésien de tous les éléments.
Dans l'exemple suivant, un événement $e avec deux valeurs répétées sur security_results et deux valeurs répétées sur security_results.actions est déplié en quatre instances.
rule security_action_per_app {
meta:
events:
$e.principal.application = $app
match:
$app over 10m
outcome:
$security_action_count = count($e.security_results.actions) // yields 4.
condition:
$e
}
Enregistrement d'événement avant la suppression de l'imbrication
L'enregistrement d'origine stocke les actions dans une structure de tableau imbriquée.
| metadata.id | principal.application | security_results |
|---|---|---|
aaaaaaaaa |
Google SecOps |
[ { actions: [ ALLOW, FAIL ] }, { actions: [ CHALLENGE, BLOCK ] } ] |
Enregistrements d'événements après l'annulation de l'imbrication
Après l'expansion, chaque action unique devient sa propre ligne, ce qui peut entraîner des nombres inattendus dans les agrégations non distinctes.
| metadata.id | principal.application | security_results.actions |
|---|---|---|
aaaaaaaaa |
Google SecOps |
AUTORISER |
aaaaaaaaa |
Google SecOps |
ÉCHEC |
aaaaaaaaa |
Google SecOps |
DÉFI |
aaaaaaaaa |
Google SecOps |
BLOQUER |
Impact sur les champs non associés
Ce comportement de suppression de l'imbrication lors de l'évaluation des règles peut produire des agrégations de résultats inattendues lorsque la règle fait référence à un ou plusieurs champs répétés avec un champ parent qui est également un champ répété. Les agrégations non distinctes telles que sum(), array() et count() ne peuvent pas tenir compte des valeurs en double dans d'autres champs du même événement généré par le comportement de désimbrication.
Dans l'exemple suivant, l'événement $e ne comporte qu'un seul nom d'hôte (google.com), mais le résultat (hostnames) agrège quatre instances non imbriquées du même événement $e, chacune avec une valeur principal.hostname en double. Ce résultat génère quatre noms d'hôte (au lieu d'un) en raison de l'annulation de l'imbrication des valeurs répétées sur security_results.actions.
rule security_action_per_app {
meta:
events:
$e.principal.application = $app
match:
$app over 10m
outcome:
$hostnames = array($e.principal.hostname) // yields 4.
$security_action_count = count($e.security_results.action) // yields 4.
condition:
$e
}
Enregistrement d'événement avant la suppression de l'imbrication avec des champs sans rapport
Le nom d'hôte est une valeur unique, mais il se trouve à côté des résultats de sécurité répétés.
| metadata.id | principal.application | principal.hostname | security_results |
|---|---|---|---|
aaaaaaaaa |
Google SecOps |
google.com |
[ { action: [ ALLOW, FAIL ] }, { action: [ CHALLENGE, BLOCK ] } ] |
Enregistrement d'événement après l'annulation de l'imbrication avec des champs non liés
Le nom d'hôte est désormais dupliqué sur quatre lignes, ce qui fait que la fonction array() le récupère quatre fois.
| metadata.id | principal.application | principal.hostname | security_results.action |
|---|---|---|---|
aaaaaaaaa |
Google SecOps |
google.com |
AUTORISER |
aaaaaaaaa |
Google SecOps |
google.com |
ÉCHEC |
aaaaaaaaa |
Google SecOps |
google.com |
DÉFI |
aaaaaaaaa |
Google SecOps |
google.com |
BLOQUER |
Solution de contournement pour le comportement de désimbrication
Pour vous assurer que vos valeurs de résultat sont exactes lorsque l'opération d'annulation de l'imbrication se produit, utilisez la version distincte de l'agrégation sélectionnée. Les fonctions suivantes ignorent les lignes en double créées par la désimbrication :
max()min()array_distinct()count_distinct()
Agrégations de résultats avec plusieurs variables d'événement
Si une règle contient plusieurs variables d'événement, il existe un élément distinct dans l'agrégation pour chaque combinaison d'événements incluse dans la détection. Par exemple, si la règle suivante est exécutée sur les événements listés :
events:
$e1.field = $e2.field
$e2.somefield = $ph
match:
$ph over 1h
outcome:
$some_outcome = sum(if($e1.otherfield = "value", 1, 0))
condition:
$e1 and $e2
event1:
// UDM event 1
field="a"
somefield="d"
event2:
// UDM event 2
field="b"
somefield="d"
event3:
// UDM event 3
field="c"
somefield="d"
La somme est calculée pour chaque combinaison d'événements, ce qui vous permet d'utiliser les deux variables d'événement dans les calculs de la valeur du résultat. Les éléments suivants sont utilisés dans le calcul :
1: $e1 = event1, $e2 = event2
2: $e1 = event1, $e2 = event3
3: $e1 = event2, $e2 = event1
4: $e1 = event2, $e2 = event3
5: $e1 = event3, $e2 = event1
5: $e1 = event3, $e2 = event2
La somme maximale potentielle est donc de 6, même si $e2 ne peut correspondre qu'à trois événements distincts.
Cela affecte la somme, le nombre et le tableau. Pour les types "count" et "array", vous pouvez résoudre le problème en utilisant count_distinct ou array_distinct, mais il n'existe aucune solution de contournement pour le type "sum".
Parenthèses au début d'une expression
Il n'est pas possible de commencer une expression par des parenthèses. Cela déclenche une erreur d'analyse dans l'éditeur de règles.
Syntaxe incorrecte
parsing: error with token: ")"
invalid operator in events predicate
L'exemple suivant génère ce type d'erreur :
($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600 > 1
Variantes de syntaxe valides
Les variations de syntaxe suivantes renvoient le même résultat, mais avec une syntaxe valide :
$event.metadata.ingested_timestamp.seconds / 3600 -
$event.metadata.event_timestamp.seconds / 3600 > 1
1 / 3600 * ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) > 1
1 < ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600
Le tableau d'index du résultat nécessite une agrégation
L'indexation directe d'un tableau dans la section outcome pour les champs répétés n'est pas autorisée. Elle nécessite une variable d'espace réservé temporaire.
outcome:
$principal_user_dept = $suspicious.principal.user.department[0]
Solution
Capturez l'index de tableau spécifique dans une variable d'espace réservé dans la section events, puis référencez cet espace réservé dans votre résultat.
events:
$principal_user_dept = $suspicious.principal.user.department[0]
outcome:
$principal_user_department = $principal_user_dept
Condition OR avec non-existence
Si vous appliquez une condition OR entre deux variables d'événement distinctes et que la règle correspond à une non-existence, la règle est compilée avec succès, mais peut générer des faux positifs.
Par exemple, la syntaxe de règle suivante peut correspondre à des événements comportant $event_a.field = "something", même si ce n'est pas le cas :
events:
not ($event_a.field = "something" **or** $event_b.field = "something")
condition:
$event_a and #event_b >= 0
Solution
Séparez les vérifications d'inexistence en blocs individuels pour chaque variable afin de préserver l'intégrité logique.
events:
not ($event_a.field = "something")
not ($event_b.field = "something")
condition:
$event_a and #event_b >= 0
Arithmétique avec des champs d'événement non signés
Si vous essayez d'utiliser une constante entière dans une opération arithmétique avec un champ UDM dont le type est un entier non signé, une erreur s'affiche. Exemple :
events:
$total_bytes = $e.network.received_bytes * 2
Les constantes entières standards sont définies par défaut sur des entiers signés, qui sont incompatibles avec les champs UDM définis comme des entiers non signés, comme network.received_bytes.
Solution
Vous pouvez contourner cette erreur en forçant la constante entière à se comporter comme un float via une opération de division.
events:
$total_bytes = $e.network.received_bytes * (2/1)
Enrichissement GeoIP et cohérence à terme
Le système privilégie la vitesse par rapport à la précision immédiate lors des étapes d'enrichissement initiales (Streaming et Sensible à la latence), ce qui peut entraîner des données manquantes et de potentiels faux positifs. Le système continue d'enrichir les données en arrière-plan, mais il est possible qu'elles ne soient pas disponibles lorsque la règle est exécutée. Cela fait partie du processus normal de cohérence éventuelle.
Pour éviter les faux positifs causés par le décalage de l'enrichissement, vérifiez explicitement que le champ n'est pas vide avant d'évaluer sa valeur.
Prenons l'exemple de l'événement de règle suivant :
$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"
La règle repose sur le fait que l'événement doit comporter $e.principal.ip_geo_artifact.network.asn = "16509" ET $e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom", qui sont tous deux des champs enrichis. Si l'enrichissement n'est pas terminé à temps, la règle génère un faux positif.
Pour éviter cela, une meilleure vérification de cette règle serait :
$e.principal.ip_geo_artifact.network.asn != "" AND
$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region != "" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"
Cette règle élimine la possibilité que l'événement soit déclenché par des adresses IP avec l'ASN 16509, mais situées en dehors du Royaume-Uni. Cela améliore la précision globale de la règle.
Découvrez comment résoudre les problèmes liés au décalage de l'enrichissement.
Dépannage
Cette section décrit les attentes en termes de performances et fournit des solutions en libre-service pour les problèmes courants où le comportement de la détection en direct diffère des résultats des tests.
Événements futurs
Les règles multi-événements sont conçues pour traiter les événements dans l'ordre chronologique par rapport à l'ingestion. Si vous spécifiez et activez une règle multi-événements, elle ne crée pas de détections pour les événements dont les codes temporels sont futurs, par exemple lorsque la date et l'heure de event.timestamp sont définies après celles de ingest.timestamp.
Délai d'enrichissement
Google SecOps donne la priorité à la vitesse d'ingestion pour exposer les alertes initiales le plus rapidement possible. Toutefois, les processus d'enrichissement en arrière-plan, tels que la résolution des métadonnées GeoIP, ASN ou UDM, suivent un modèle de cohérence à terme.
Exécution initiale (T₀)
Il est possible que le moteur de diffusion en direct évalue une règle avant que l'enrichissement en arrière-plan ne soit terminé. Selon que votre logique repose sur des champs enrichis pour les détections ou les exclusions, cela peut entraîner les écarts temporaires suivants :
Faux négatifs (délai de détection) : il s'agit d'un résultat courant. Si une règle dépend d'un champ enrichi pour se déclencher (par exemple,
target.user.department == "Finance") et que ce champ estnull, la règle ne correspond pas lors de la première exécution.Faux positifs (exclusion manquée) : si votre règle utilise des champs enrichis pour filtrer les activités connues comme valides (par exemple,
NOT target.ip_geo_country == "US"), elle peut déclencher un faux positif, car les données d'exclusion n'ont pas encore été appliquées.
Exécutions de régularisation
Ces exécutions en arrière-plan réévaluent les données après un certain délai (par exemple, 45 minutes ou 30 heures). Les états de détection sont alors corrigés comme suit :
Détections tardives : les événements qui étaient des "faux négatifs" à T₀ génèrent désormais une détection une fois l'enrichissement terminé.
Correction : tous les faux positifs T₀ restent dans le système, mais les données entièrement enrichies sont visibles dans l'outil d'affichage UDM pour le tri manuel.
Exécuter le test des écarts
L'outil Exécuter le test fonctionne sur des données historiques déjà réconciliées. Étant donné que les données sont entièrement enrichies au moment où vous exécutez un test manuel, vous pouvez voir immédiatement les résultats de la mise à jour. Cela signifie que vous ne verrez pas les faux négatifs T₀ ni les faux positifs basés sur l'exclusion qui se sont produits lors de l'exécution initiale en direct.
Correction des erreurs
Utilisez le tableau ci-dessous pour résoudre les écarts entre les alertes en direct et les résultats des tests.
| Problème | Description | Correction exploitable |
|---|---|---|
| Échec de l'exclusion | Une règle se déclenche malgré une exclusion (par exemple, != "ASN_123"), car le champ était nul lors de la première exécution. |
Ajoutez une vérification "not null" à la section des événements pour vous assurer que les données sont enrichies avant l'évaluation, par exemple :$e.principal.ip_geo_artifact.network.asn != ""
|
| Comparaison entre les matchs réels et les matchs tests | Les règles en direct déclenchent des alertes, mais l'option "Exécuter le test" sur les mêmes données affiche "No Results. |
Ajoutez $e.field != "", qui vérifie tous les champs enrichis (GeoIP, ASN, File Path) pour synchroniser le comportement en direct et historique. |
| Métadonnées manquantes | Les détections s'affichent dans le tableau de bord avec des champs GeoIP ou File Path vides. |
Ce comportement est normal pour les exécutions T0. Pour résoudre ce problème, incluez une vérification field != "" ou augmentez le décalage de la première exécution dans votre calendrier d'exécution afin de laisser plus de temps pour l'ingestion.
|
Validation et test
Pour vérifier qu'une règle gère correctement l'enrichissement différé, procédez comme suit :
Identifier le décalage : localisez une détection qui vous semble être un faux positif. Dans la colonne Type de détection, recherchez l'icône
<span class="material-icons">lightbulb</span>. Les alertes sans cette icône proviennent de la première exécution, où le décalage de l'enrichissement est le plus fréquent.Mettez à jour la logique de la règle : ajoutez une vérification
field != ""pour tous les points de données enrichis utilisés dans votre logique.
Exemple (chemin d'accès au fichier) :
$e.target.process.parent_process.file.full_path != ""Testez et vérifiez :
- Utilisez la fonctionnalité Exécuter le test pour vous assurer que votre logique correspond toujours aux données historiques prévues.
- Vérifiez que la règle ne se déclenche désormais que lors des ajustements (ou qu'elle exclut correctement les données) une fois les champs d'enrichissement renseignés.
Pour en savoir plus, consultez Gérer la planification de l'exécution de vos règles et Configurer des plannings personnalisés pour les règles.
Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.