Syntaxe de la section "outcome"
La section outcome d'une requête YARA-L définit les variables de résultat qui spécifient la sortie d'une requête de recherche et de tableau de bord, ainsi que le contexte et les informations supplémentaires d'une détection lorsqu'une règle est déclenchée. Ces variables peuvent être utilisées à différentes fins, par exemple pour afficher des données pertinentes sur des tableaux de bord et créer des scores de risque.
Section "Définir le résultat"
Utilisez le caractère $, suivi d'un nom de variable, pour définir une variable de résultat dans la section outcome d'une seule requête. Vous pouvez définir jusqu'à 20 variables de résultat. Les noms des variables sont arbitraires. Pour les règles, les valeurs de résultat sont calculées et agrégées en fonction de chaque détection.
Chaque variable de résultat se voit attribuer une valeur à l'aide d'une expression.
Cette règle recherche les échecs de connexion depuis un nouvel emplacement :
rule failed_logins
{
meta:
author = "Security Team"
description = "Detects multiple failed user logins within 10-minute windows."
severity = "HIGH"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.security_result.action = "FAIL"
$user = $e.target.user.userid
match:
$user over 10m
outcome:
$failed_login_count = count($e.metadata.id)
$first_fail_time = min($e.metadata.event_timestamp.seconds)
condition:
#e >= 5
}
La section outcome effectue des agrégations sur les variables d'événement et d'espace réservé : elle compte les connexions ayant échoué, compte les adresses IP distinctes et obtient l'heure à laquelle l'échec s'est produit.
outcome:
$failed_login_count = count($e.metadata.id)
$first_fail_time = min($e.metadata.event_timestamp.seconds)
Si vous incluez et renseignez la variable de résultat spéciale $risk_score, sa valeur (entier ou flottant) s'affiche sur la page Alertes et IoC pour les alertes générées par la requête.
Si vous n'incluez pas de variable $risk_score dans la section outcome d'une requête, l'une des valeurs par défaut suivantes est définie :
Si la requête est configurée pour générer une alerte,
$risk_scoreest défini sur 40.Si la requête n'est pas configurée pour générer une alerte,
$risk_scoreest défini sur 15.
La valeur de $risk_score est stockée dans le champ UDM security_result.risk_score.
variable de résultat risk_score
Google SecOps Risk Analytics associe automatiquement les détections et les alertes aux entités qui leur sont liées. La variable de résultat risk_score permet d'attribuer un niveau de risque. Si cette valeur n'est pas définie, la valeur de détection ou d'alerte par défaut est utilisée. Vous pouvez configurer des valeurs par défaut dans les paramètres.
Pour garantir la cohérence sur l'ensemble de la plate-forme, nous vous recommandons d'utiliser les plages de scores suivantes lorsque vous attribuez un risk_score à vos détections personnalisées. Cet alignement permet de standardiser la priorisation des alertes et les workflows de réponse.
| Gravité | Plage de scores | Description | Exemple |
|---|---|---|---|
| Alerte : critique | 90 - 100 | Compromission active susceptible d'avoir un impact au-delà d'un seul compte utilisateur ou d'un seul point de terminaison. Examen immédiat requis. | Mimikatz exécuté sur le contrôleur de domaine. |
| Alerte : élevée | 80 - 89 | Compromission active d'un seul point de terminaison ou d'une seule entité. Doit être examiné immédiatement. | Serveur de production appelant un C2 récent et connu. |
| Alertes – Moyenne | 50 - 79 | Problème de sécurité potentiel nécessitant une investigation. Aucune compromission confirmée, mais une escalade est possible. | Un identifiant exposé, aucun signe d'utilisation abusive. |
| Sans alerte – Faible | 20 à 49 | Événement de sécurité à faible impact qui, lorsqu'il est combiné à d'autres indicateurs ou observations, peut entraîner un incident plus important. Aucun examen n'est généralement nécessaire. Peut être combiné à d'autres détections via des règles composites pour créer une alerte. | Analyse des ports internes. |
| Observations sans alerte | 1 à 19 | En général, il s'agit de détections basées sur des informations destinées à sensibiliser à une menace. En général, ne nécessite pas d'examen. Peut être combiné avec d'autres détections via des règles composites pour générer des alertes. | Un événement de connexion, aucun signe d'utilisation abusive. |
Étant donné que risk_score est une variable de résultat, vos règles peuvent exprimer des nuances en fonction de facteurs tels que les renseignements sur les menaces ou d'autres conditions simultanées.
Les scores de risque des entités peuvent être utilisés pour générer des alertes basées sur les risques en temps quasi réel. Pour en savoir plus, consultez la présentation de Risk Analytics.
Variable de résultat risk_entity_to_score
Par défaut, Google SecOps attribue un score de risque de détection à toutes les entités des événements échantillonnés. Il attribue également le score à toutes les entités capturées dans les sections match et outcome de la règle. Pour attribuer le score de risque à des entités spécifiques, spécifiez la variable de résultat risk_entity_to_score en plus de risk_score. Le scoring de risque est compatible avec les entités user et asset. Il n'est pas compatible avec les types d'entités RESOURCE ou GROUP.
Vous pouvez créer plusieurs variables risk_entity_to_score en ajoutant une chaîne unique à la variable et en attribuant le score de risque à des entités spécifiques. Exemple :
$risk_entity_to_score_source_asset = $e.principal.asset.hostname
$risk_entity_to_score_targeted_user = $e.target.user.userid
Ces variables de résultat attribuent la valeur risk_score spécifiée dans la section outcome de la règle aux entités $e.principal.asset.hostname et $e.target.user.userid.
Exemple : La règle détecte les connexions aux comptes administrateur
Cette règle détecte les connexions réussies à des comptes administrateur à privilèges élevés. Il utilise le mot clé risk_entity_to_score pour cibler explicitement l'utilisateur spécifique qui se connecte. À l'aide de cette variable, la détection garantit que le score de risque calculé ne s'applique qu'à cet utilisateur, et non aux autres entités impliquées dans l'événement, telles que l'adresse IP source.
Pour savoir comment rédiger une règle multi-événement, consultez Règle multi-événement.
rule suspicious_admin_privilege_escalation {
// This rule matches single events. Rules can also match multiple events within
// the same time window.
meta:
// Allows for storage of arbitrary key-value pairs of rule details, such as
// who wrote it, what it detects on, and version control.
// The "author" and "severity" fields are special, since they are used as
// columns on the rules dashboard. To sort based on these fields on the
// dashboard, add them here.
// Severity value should be "Low", "Medium", or "High"
author = "analyst123"
description = "Detects suspicious login to critical admin accounts."
severity = "HIGH"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.target.user.attribute.roles.name = "ADMIN"
$e.security_result.summary = "Successful login with high-privilege access"
outcome:
// Multi-event rules require an aggregation function
// For example, risk_score = max(0)
// See https://docs.cloud.google.com/chronicle/docs/yara-l/yara-l-2-0-examples#outcome_conditionals_example_rule
$risk_score = 80
$risk_entity_to_score = $e.target.user.userid
$source_ip = array_distinct($e.principal.ip)
condition:
$e
}
Exemple : Règle surveillant les connexions réseau internes
Cette règle vérifie les mouvements latéraux en identifiant les connexions réseau entre les segments de réseau internes. Il utilise $risk_entity_to_score prefix pour attribuer un risque à plusieurs entités au sein d'une même détection. Les scores de risque de l'hôte initiateur ($risk_entity_to_score_source_asset) et de l'utilisateur ciblé ($risk_entity_to_score_targeted_user) sont mis à jour. Le moteur de risque enregistre d'autres variables de résultat qui n'utilisent pas ce préfixe spécifique pour le contexte, mais les ignore (leurs scores de risque restent les mêmes).
Pour savoir comment rédiger une règle multi-événement, consultez Règle multi-événement et Exemple de règle de conditions de résultat.
rule lateral_movement_network_connection {
// This rule matches single events. You can also match multiple events within
// the same time window.
meta:
// Allows for storage of arbitrary key-value pairs of rule details (for
// example, who wrote it, what it detects on, and version control).
// The "author" and "severity" fields are special, since they are used as
// columns on the rules dashboard. To sort based on these fields on the
// dashboard, add them here. Severity value should be "Low", "Medium" or "High"
author = "analyst123"
description = "Detects lateral movement attempts between internal segments."
severity = "MEDIUM"
events:
$e.metadata.event_type = "NETWORK_CONNECTION"
$e.principal.asset.hostname != ""
$e.target.user.userid != ""
// Can also use: $e.target.ip = /10\..*/
net.ip_in_range_cidr($e.target.ip, "10.0.0.0/8")
outcome:
// Multi-event rules require an aggregation function
// for example, risk_score = max(0)
// See https://docs.cloud.google.com/chronicle/docs/yara-l/yara-l-2-0-examples#outcome-conditionals-example-rule
$risk_score = 50
$risk_entity_to_score_source_asset = $e.principal.asset.hostname
$risk_entity_to_score_targeted_user = $e.target.user.userid
$target_ip_info = array_distinct($e.target.ip)
condition:
$e
}
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 la calculer. Les types de données de résultat suivants sont compatibles avec Google SecOps :
- entier
- floats
- string
- listes d'entiers
- listes de nombres à virgule flottante
- listes de chaînes
Logique conditionnelle
Vous pouvez utiliser une 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 comme suit : "si BOOL_CLAUSE est vrai, renvoyer THEN_CLAUSE, sinon renvoyer ELSE_CLAUSE".
BOOL_CLAUSE doit renvoyer une valeur booléenne. Une expression BOOL_CLAUSE prend une forme similaire aux expressions de la section events. Par exemple, il peut contenir :
Noms de champs UDM avec opérateur de comparaison :
if($context.graph.entity.user.title = "Vendor", 100, 0)Variable d'espace réservé définie dans la section
events:if($severity = "HIGH", 100, 0)Une autre variable de résultat définie dans la section
outcome:if($risk_score > 20, "HIGH", "LOW")Fonctions qui renvoient une valeur booléenne :
if(re.regex($e.network.email.from, `.*altostrat.com`), 100, 0)Rechercher dans une liste de référence :
if($u.principal.hostname in %my_reference_list_name, 100, 0)Comparaison d'agrégation :
if(count($login.metadata.event_timestamp.seconds) > 5, 100, 0)
THEN_CLAUSE et ELSE_CLAUSE doivent être du même type de données. Nous acceptons les entiers, les nombres à virgule flottante et les chaînes.
Vous pouvez omettre ELSE_CLAUSE si le type de données est un entier ou un float. Si elle est omise, ELSE_CLAUSE renvoie 0. Exemple :
`if($e.field = "a", 5)` is equivalent to `if($e.field = "a", 5, 0)`
Vous devez fournir ELSE_CLAUSE si le type de données est une chaîne ou si THEN_CLAUSE est une variable d'espace réservé ou une variable de résultat.
Opérations mathématiques
Vous pouvez utiliser des opérations mathématiques pour calculer des types de données entiers ou à virgule flottante dans les sections outcome et events d'une requête. Google Security Operations accepte l'addition, la soustraction, la multiplication, la division et le modulo en tant qu'opérateurs de premier niveau dans un calcul.
L'extrait de code suivant est un exemple de calcul dans la section outcome :
outcome:
$risk_score = max(100 + if($severity = "HIGH", 10, 5) - if($severity = "LOW", 20, 0))
Les opérations mathématiques sont autorisées sur les types d'opérandes suivants, à condition que chaque opérande et l'expression arithmétique entière soient correctement agrégés (voir Agrégations) :
- Champs d'événement numériques
- Variables d'espaces réservés numériques définies dans la section
events - Variables de résultat numériques définies dans la section
outcome - Fonctions renvoyant des entiers ou des nombres à virgule flottante
- Agrégations renvoyant des entiers ou des nombres à virgule flottante
Le modulo n'est pas autorisé sur les nombres à virgule flottante.
Les littéraux d'entiers standards sont par défaut des entiers signés de 64 bits (INT64), qui sont incompatibles avec les champs UDM d'entiers non signés de 64 bits (UINT64), tels que network.received_bytes, network.sent_bytes et principal.file.size.
La combinaison de ces types dans des opérations arithmétiques (+, -, *) ou modulo (%) peut entraîner une erreur d'exécution dans la section outcome. Pour résoudre ce problème, utilisez cast.as_int() ou cast.as_uint() pour faire correspondre les types d'entiers. Le transtypage explicite est requis pour l'opérateur %. Pour les opérations arithmétiques, vous pouvez également forcer les constantes entières à se comporter comme des nombres à virgule flottante à l'aide de littéraux à virgule flottante, tels que 2.0 ou 100.0, ou de la coercition de division, telle que (2/1), dans des expressions sans autres opérateurs / sur la même ligne. Pour en savoir plus, consultez Arithmétique avec des champs d'événement non signés.
Variables d'espace réservé dans les résultats
Lors du calcul des variables de résultat, vous pouvez utiliser des variables d'espace réservé qui ont été définies dans la section "events" de votre requête. Dans cet exemple, supposons que $email_sent_bytes a été défini dans la section des événements de la règle :
Exemple : événement unique sans section de correspondance
// No match section, so this is a single-event query. 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 : règle à événements multiples avec section "match"
match:
// This is a multi event query 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.0
+ $email_sent_bytes
+ $file_event.principal.file.size
)
condition:
$email_event and $file_eventVariables de résultat dans les expressions d'attribution de résultat
Les variables de résultat peuvent être utilisées pour dériver d'autres variables de résultat, de la même manière que les variables d'espace réservé définies dans la section events. Vous pouvez faire référence à une variable de résultat dans l'attribution d'une autre variable de résultat avec un jeton $ suivi du nom de la variable. Les variables de résultat doivent être définies avant de pouvoir être référencées dans le texte de la requête. Lorsqu'elles sont utilisées dans une expression d'attribution, les variables de résultat ne doivent pas être agrégées (voir Agrégations).
Dans l'exemple suivant, la variable de résultat $risk_score dérive sa valeur de la variable de résultat $event_count :
Exemple : Variable de résultat dérivée d'une autre variable de résultat
match: // This is a multi event query with a match section. $hostname over 5m outcome: // Aggregates all timestamp on login events in the 5 minute match window. $event_count = count($login.metadata.event_timestamp.seconds) // $event_count cannot be aggregated again. $risk_score = if($event_count > 5, "SEVERE", "MODERATE") // This is the equivalent of the 2 outcomes combined. $risk_score2 = if(count($login.metadata.event_timestamp.seconds) > 5, "SEVERE", "MODERATE") condition: $e
Les variables de résultat peuvent être utilisées dans n'importe quel type d'expression sur le côté droit d'une attribution de résultat, à l'exception des expressions suivantes :
- Agrégations
- Appels de fonctions
Arrays.length() - Avec les modificateurs
anyouall
Agrégations
Les champs d'événement répétés sont des valeurs non scalaires. Autrement dit, une seule variable pointe vers plusieurs valeurs. Par exemple, la variable de champ d'événement $e.target.ip est un champ répété et peut comporter zéro, une ou plusieurs valeurs d'adresse IP. Il s'agit d'une valeur non scalaire. En revanche, la variable de champ d'événement $e.principal.hostname n'est pas un champ répété et ne comporte qu'une seule valeur (c'est-à-dire une valeur scalaire).
De même, les champs d'événement non répétés et les champs d'événement répétés utilisés dans la section outcome d'une requête avec une période de correspondance sont des valeurs non scalaires.
Exemple : Regrouper des événements avec une section de correspondance et un champ non répété
La requête suivante regroupe les événements à l'aide d'une section "match" et fait référence à un champ d'événement non répété dans la section "outcome" :
rule OutcomeAndMatchWindow{
...
match:
$userid over 5m
outcome:
$hostnames = array($e.principal.hostname)
...
}Toute fenêtre de cinq minutes sur laquelle la requête s'exécute peut contenir zéro, un ou plusieurs événements. La section "outcome" s'applique à tous les événements d'une fenêtre de correspondance. Toute variable de champ d'événement référencée dans la section "outcome" peut pointer vers zéro, une ou plusieurs valeurs du champ sur chaque événement de la fenêtre de correspondance.
Par exemple, si une fenêtre de cinq minutes contient cinq événements $e, $e.principal.hostname dans la section des résultats pointe vers cinq noms d'hôte différents. La variable de champ d'événement $e.principal.hostname est traitée comme une valeur non scalaire dans la section outcome de cette requête.
Étant donné que les variables de résultat doivent toujours générer une seule valeur scalaire, toute valeur non scalaire dont dépend une attribution de résultat doit être agrégée pour générer une seule valeur scalaire. Dans une section de résultat, les valeurs suivantes sont non scalaires et doivent être agrégées :
- Champs d'événement (répétés ou non) lorsque la requête utilise une section
match - Espaces réservés d'événement (répétés ou non) lorsque la requête utilise une section
match - Champs d'événement répétés lorsque la requête n'utilise pas de section
match - Espaces réservés d'événements périodiques lorsque la requête n'utilise pas de section
match
Les champs d'événement scalaires, les espaces réservés d'événement scalaires et les constantes peuvent être encapsulés dans des fonctions d'agrégation dans les requêtes qui n'incluent pas de section match. Cependant, dans la plupart des cas, ces agrégations renvoient la valeur encapsulée, ce qui les rend inutiles.
L'agrégation array() constitue une exception, car elle vous permet de convertir explicitement une valeur scalaire en tableau.
Les variables de résultat sont traitées comme des agrégations : elles ne doivent pas être réagrégées lorsqu'elles sont référencées dans une autre attribution de résultat.
Vous pouvez utiliser les fonctions d'agrégation suivantes :
| Fonction d'agrégation | Description |
|---|---|
max() |
Renvoie la valeur maximale parmi toutes les valeurs possibles. Ne fonctionne qu'avec les entiers et les nombres à virgule flottante. |
min() |
Renvoie la valeur minimale parmi toutes les valeurs possibles. Ne fonctionne qu'avec les entiers et les nombres à virgule flottante. |
sum() |
Renvoie la somme de toutes les valeurs possibles. Ne fonctionne qu'avec les entiers et les nombres à virgule flottante. |
count_distinct() |
Collecte toutes les valeurs possibles, puis affiche le nombre de valeurs possibles distinctes. |
count() |
Se comporte comme "count_distinct()", mais renvoie un nombre non distinct de valeurs possibles. |
array_distinct() |
Collecte toutes les valeurs distinctes possibles, puis génère une liste de ces valeurs. La déduplication pour produire une liste distincte est appliquée en premier, puis la troncature est appliquée. Dans la recherche, la liste est tronquée à un maximum de 1 000 éléments aléatoires. Dans les tableaux de bord et les règles, la liste est tronquée à un maximum de 25 éléments aléatoires. |
array() |
Se comporte comme array_distinct(), mais renvoie une liste de valeurs non distinctes. Dans la recherche, la liste est tronquée à un maximum de 1 000 éléments aléatoires. Dans les tableaux de bord et les règles, la liste est tronquée à un maximum de 25 éléments aléatoires. |
La fonction d'agrégation est importante lorsqu'une règle inclut une section condition qui spécifie que plusieurs événements doivent exister, car la fonction d'agrégation s'applique à tous les événements qui ont généré la détection.
Exemple : Condition pour plusieurs événements
Voici un exemple de condition pour plusieurs événements. Si la section "Résultat et condition" contient :
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 "condition" nécessite plusieurs "événements" pour chaque détection, les fonctions d'agrégation s'appliquent à 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"]
Limites
La section
outcomene peut pas référencer une nouvelle variable d'espace réservé qui n'a pas déjà été définie dans la sectioneventsou dans la sectionoutcome.La section
outcomene peut pas utiliser de variables d'événement qui n'ont pas été définies dans la sectionevents.La section
outcomepeut utiliser un champ d'événement qui n'a pas été utilisé dans la sectionevents, étant donné que la variable d'événement à laquelle appartient le champ d'événement a déjà été définie dans la sectionevents.La section
outcomene peut mettre en corrélation que les variables d'événement qui ont déjà été mises en corrélation dans la sectionevents. Les corrélations se produisent lorsque deux champs d'événement provenant de variables d'événement différentes sont mis en équivalence.
Consultez la Présentation de YARA-L 2.0 pour obtenir des exemples de la section outcome.
Pour en savoir plus sur la déduplication des détections avec la section outcome, consultez Créer des analyses contextuelles.
Étapes suivantes
Informations supplémentaires
- Expressions, opérateurs et constructions utilisés dans YARA-L 2.0
- Fonctions dans YARA-L 2.0
- Créer des règles de détection composites
- Exemples : requêtes YARA-L 2.0
Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.