Syntaxe de la section "Résultat"

Compatible avec :

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 pour une détection lorsqu'une règle est déclenchée. Ces variables peuvent être utilisées à diverses fins, par exemple pour afficher des données pertinentes dans les tableaux de bord et créer des scores de risque.

Définir la section "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 de variables eux-mêmes sont arbitraires. Pour les règles, les valeurs de résultat sont calculées et agrégées en fonction de chaque détection.

Une valeur est attribuée à chaque variable de résultat à 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 échecs de connexion, 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 (nombre 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_score est défini sur 40.

  • Si la requête n'est pas configurée pour générer une alerte, $risk_score est défini sur 15.

La valeur de $risk_score est stockée dans le champ UDM security_result.risk_score.

Variable de résultat du score de risque

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 est utilisée pour 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 assurer 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 hiérarchisation des alertes et les workflows de réponse.

Gravité Plage de scores Description Exemple
Alertes : critique 90 - 100 Compromission active susceptible d'avoir un impact au-delà d'un seul compte utilisateur ou point de terminaison. Nécessite un examen immédiat. Mimikatz a été exécuté sur le contrôleur de domaine.
Alertes : niveau élevé 80 - 89 Compromission active d'un seul point de terminaison ou d'une seule entité. Doit faire l'objet d'un examen immédiat. Serveur de production appelant un C2 récent et connu.
Alertes : moyen 50 - 79 Problème de sécurité potentiel nécessitant une enquête. Aucune compromission confirmée, mais l'escalade est possible. Identifiant exposé, sans signe d'utilisation abusive.
Non-Alerting – Low 20 à 49 Événement de sécurité à faible impact qui, combiné à d'autres indicateurs ou observations, peut entraîner un incident plus grave. Aucune vérification n'est généralement nécessaire. Cette détection peut être combinée à d'autres détections via des règles composites pour créer une alerte. Analyse interne des ports.
Observations sans alerte 1 à 19 Il s'agit généralement de détections basées sur des informations visant à mieux comprendre une menace. Ne nécessite généralement pas d'examen. Peut être combiné avec d'autres détections via des règles composites pour générer des alertes. É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 le renseignement 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 le risque en temps quasi réel. Pour en savoir plus, consultez Présentation de Risk Analytics.

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ésultats suivants sont acceptés dans Google SecOps :

  • entier
  • nombres à virgule flottante
  • string
  • listes d'entiers
  • listes de valeurs flottantes
  • 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 true, renvoie THEN_CLAUSE, sinon renvoie ELSE_CLAUSE".

BOOL_CLAUSE doit renvoyer une valeur booléenne. Une expression BOOL_CLAUSE prend une forme semblable à celle des 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)

  • 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érences :

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

  • Comparaison de l'agrégation :

    if(count($login.metadata.event_timestamp.seconds) > 5, 100, 0)

THEN_CLAUSE et ELSE_CLAUSE doivent correspondre au même type de données. Nous acceptons les entiers, les valeurs à 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, la valeur de ELSE_CLAUSE est définie sur 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 flottants 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 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'ensemble de l'expression arithmétique soient correctement agrégés (voir Agrégations) :

  • Champs d'événements numériques
  • Variables d'espace réservé numériques définies dans la section events
  • Variables de résultat numériques définies dans la section outcome
  • Fonctions renvoyant des nombres entiers ou à virgule flottante
  • Agrégations renvoyant des entiers ou des nombres à virgule flottante

Le module n'est pas autorisé sur les nombres à virgule flottante.

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

Lorsque vous calculez des variables de résultat, vous pouvez utiliser des variables de substitution définies dans la section "Événements" de votre requête. Dans cet exemple, supposons que $email_sent_bytes a été défini dans la section "É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 : événement multiple avec section de correspondance

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
    + $email_sent_bytes
    + $file_event.principal.file.size
  )

condition:
  $email_event and $file_event

Variables de résultat dans les expressions d'attribution des résultats

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 tire 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 à droite d'une attribution de résultat, sauf dans les expressions suivantes :

  • Agrégations
  • Appels de fonctions Arrays.length()
  • Avec les modificateurs any ou all

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 avoir 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 fenêtre 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 période de cinq minutes sur laquelle la requête s'exécute peut contenir zéro, un ou plusieurs événements. La section "Résultat" fonctionne sur tous les événements d'une fenêtre de match. Toute variable de champ d'événement mentionnée dans la section "Résultat" peut pointer vers zéro, une ou plusieurs valeurs du champ pour chaque événement de la période de correspondance. Par exemple, si une période de cinq minutes contient cinq événements $e, $e.principal.hostname dans la section "Résultat" 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 sur les résultats, les valeurs non scalaires suivantes 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 pour les événements (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 pour les événements répétés lorsque la requête n'utilise pas de section match

Les champs d'événements scalaires, les espaces réservés d'événements 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. Toutefois, dans la plupart des cas, ces agrégations renvoient la valeur encapsulée, ce qui les rend inutiles. L'agrégation array() fait exception, car vous pouvez l'utiliser pour 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() Affiche le maximum de toutes les valeurs possibles. Ne fonctionne qu'avec les nombres entiers et à virgule flottante.
min() Affiche le minimum de toutes les valeurs possibles. Ne fonctionne qu'avec les nombres entiers et à virgule flottante.
sum() Affiche la somme de toutes les valeurs possibles. Ne fonctionne qu'avec les nombres entiers et à virgule flottante.
count_distinct() Collecte toutes les valeurs possibles, puis renvoie le nombre de valeurs distinctes possibles.
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. Elle tronque la liste des valeurs distinctes à 1 000 éléments aléatoires. La déduplication permettant d'obtenir une liste distincte est appliquée en premier, puis la troncature.
array() Se comporte comme array_distinct(), mais renvoie une liste de valeurs non distinctes. Il tronque également la liste des valeurs à 1 000 é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 fonctionnera sur 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" exige qu'il y ait plus d'un "événement" pour chaque détection, les fonctions d'agrégation fonctionneront 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 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 outcome ne peut pas faire référence à une nouvelle variable d'espace réservé qui n'a pas déjà été définie dans la section events ou dans la section outcome.

  • La section outcome ne peut pas utiliser de variables d'événement qui n'ont pas été définies dans la section events.

  • La section outcome peut utiliser un champ d'événement qui n'a pas été utilisé dans la section events, à condition que la variable d'événement à laquelle appartient le champ d'événement ait déjà été définie dans la section events.

  • La section outcome ne peut corréler que les variables d'événement qui ont déjà été corrélées dans la section events. Les corrélations se produisent lorsque deux champs d'événement provenant de variables d'événement différentes sont mis en équation.

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

Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.