Aaron Jewitt

Automatiser les demandes de réglage de la détection avec les cas Kibana

Découvrez comment automatiser les demandes d'ajustement des règles de détection dans Elastic Security. Ce guide montre comment ajouter des champs personnalisés aux cas, créer une règle pour détecter les besoins de réglage et utiliser un webhook pour créer une boucle de rétroaction sans friction entre les analystes et les ingénieurs de détection.

20 minutes de lectureMise en œuvre
Automatiser les demandes de réglage de la détection avec les cas Kibana

Automatiser les demandes de réglage de la détection avec Elastic Security

Chez Elastic, l'équipe Infosec est "Customer Zero". Nous utilisons intensivement la dernière version des produits Elastic pour sécuriser notre organisation, ce qui nous donne une vision unique de la manière de résoudre les problèmes de sécurité dans le monde réel. L'une des façons dont nous avons amélioré l'efficacité du centre d'opérations de sécurité (SOC) est de créer un flux de travail transparent et automatisé qui permet à nos analystes d'ouvrir une demande de réglage de détection directement à partir de Kibana Cases en un seul clic.

Dans tout SOC, la boucle de rétroaction entre les analystes de la sécurité et les ingénieurs de détection est cruciale pour le maintien d'une posture de sécurité saine et efficace. Les analystes en première ligne sont les premiers à voir comment les règles de détection fonctionnent dans le monde réel. Ils savent quelles alertes sont utiles, lesquelles sont bruyantes et lesquelles pourraient être améliorées avec un peu d'ajustement. La fatigue liée aux alertes bruyantes augmente le risque de passer à côté d'une véritable alerte positive. Il est essentiel de régler rapidement les faux positifs pour répondre aux vrais positifs. Capturer efficacement ce retour d'alerte peut être un défi - les processus manuels, comme l'envoi d'e-mails, l'ouverture de tickets ou les messages directs peuvent être incohérents, prendre du temps et être difficiles à suivre.

Avec Elastic Security, un analyste peut attacher des alertes à un cas nouveau ou existant dans Kibana, mener son enquête et, avec un peu de personnalisation et d'automatisation, il peut lancer une demande de réglage en un seul clic directement depuis Kibana Cases. Cet article vous expliquera comment nous avons construit cette automatisation et comment vous pouvez mettre en œuvre un système similaire pour fermer la boucle de rétroaction et optimiser votre programme de détection et de réponse.

Champs personnalisés dans les cas Kibana

Les champs personnalisés sont un élément clé de cette automatisation dans les cas Kibana. Grâce à ces champs personnalisés, nous pouvons capturer les informations nécessaires directement à partir de l'outil que les analystes utilisent déjà. Ces champs personnalisés apparaîtront sur tous les cas nouveaux et existants, offrant ainsi aux analystes un moyen clair et cohérent de signaler une détection pour examen.

Note : La possibilité d'ajouter des champs personnalisés aux dossiers a été introduite dans la version 8.15. Pour plus de détails, reportez-vous à la documentation officielle de Cases.

Chaque cas Kibana est un document stocké dans un index Elasticsearch dédié : .kibana_alerting_cases. Cela signifie que toutes vos données de cas sont disponibles pour l'interrogation, l'agrégation et l'automatisation, comme n'importe quelle autre source de données dans Elastic. Chaque dossier contient une multitude d'informations, mais quelques champs sont particulièrement utiles pour les mesures et l'automatisation. Le champ cases.status permet de savoir si un dossier est ouvert, en cours ou clôturé, tandis que cases.created_at et cases.updated_at fournissent des horodatages essentiels pour le calcul d'indicateurs tels que le délai moyen de résolution (MTTR). Des champs tels que cases.severity et cases.owner vous permettent de découper vos mesures pour voir comment l'équipe se comporte. Plus important encore pour ce blog, l'objet cases.custom_fields contient un tableau des champs personnalisés que vous avez configurés. Les champs d'exécution peuvent être utilisés pour analyser l'ensemble des champs personnalisés, ce qui vous permet de créer des requêtes, des tableaux de bord, des visualisations et des règles de détection qui déclenchent des flux de travail.

Au-delà de l'ajustement des demandes, les champs personnalisés sont incroyablement polyvalents pour le suivi des mesures et l'enrichissement des cas. Par exemple, nous disposons d'un champ personnalisé "Complex Case" pour signaler les cas dont la résolution prend plus d'une heure, ce qui nous aide à identifier les règles qui pourraient nécessiter de meilleurs guides d'investigation ou une automatisation permettant de réduire le temps d'investigation. Nous utilisons également des champs personnalisés tels que "Detection rule valid" et "True Positive Alert" pour recueillir des informations granulaires sur la performance et la fidélité des règles, ce qui nous permet de créer de puissants tableaux de bord dans Kibana pour visualiser l'efficacité opérationnelle de notre SOC.

Si vous n'avez pas encore créé une vue de données pour les informations sur les cas, vous devrez le faire si vous souhaitez utiliser des champs d'exécution et des visualisations de données avec vos cas.

Naviguez jusqu'à Index Patterns (modèles d'index) : Dans Kibana, allez à Stack Management > Data Views et cliquez sur "create new data view".

Configurez la vue Données pour mapper l'index du système .kibana_alerting_cases. Vous devrez cliquer sur le bouton Autoriser les indices cachés et les indices système pour autoriser cette opération. Pour le champ d'horodatage, je vous recommande d'utiliser le champ cases.updated_at afin que les cas soient affichés en fonction de l'activité la plus récente.

Création de champs personnalisés

Il existe deux types de champs personnalisés : les champs Text pour une saisie libre et les champs Toggle pour un simple retour d'information de type oui/non. Pour l'automatisation des demandes de réglage, nous utilisons un exemplaire de chaque. Le champ texte est un champ facultatif utilisé pour recueillir tout commentaire supplémentaire de l'analyste, et le champ bascule est utilisé pour déclencher l'automatisation.

Dans Kibana, allez sur Security > Cases, puis cliquez sur Settings en haut à droite. Dans la page des paramètres, vous verrez une section Champs personnalisés où vous pourrez ajouter les nouveaux champs que vous souhaitez. Les champs sont affichés dans l'interface utilisateur des cas par ordre alphabétique. Nous préfixons donc nos champs par des nombres pour qu'ils restent dans l'ordre souhaité.

Vous pouvez créer de nouveaux champs personnalisés, les étiquettes ajoutées dans l'interface utilisateur sont uniquement destinées aux analystes et ne sont pas stockées dans l'index des cas. Vous pouvez leur attribuer la valeur de votre choix.

Ajoutez des champs personnalisés : Nous avons besoin de deux champs pour ce flux de travail.

  • Champ 1 : Tuning Required Toggle
    • C'est sur ce bouton que les analystes cliqueront pour lancer une demande de réglage.

      • Étiquette : Open tuning request?
      • Type : Bascule
      • Valeur par défaut : Désactivé
    • Champ 2 : Détails de la demande d'accord

      • Ce champ permet à l'analyste de fournir des détails spécifiques sur ce qui doit être modifié, comme l'ajout d'une exception, la réduction de la gravité ou l'ajustement de la logique de la requête.
      • Name: Tuning request detail
      • Type : Texte
    • Valeur par défaut : Désactivé

Utiliser les champs Runtime pour mapper les champs personnalisés

L'une des difficultés rencontrées lorsque vous travaillez avec des champs personnalisés dans les cas Kibana est que le champ cases.custom_fields est mappé comme un tableau d'objets, où chaque objet représente un champ personnalisé avec son nom et sa valeur. Cette structure rend difficile la recherche de champs personnalisés spécifiques directement dans KQL. Par exemple, vous ne pouvez pas utiliser une requête telle que cases.custom_fields.open_tuning_request : "true". Pour y remédier, nous pouvons utiliser des champs d'exécution pour analyser et interroger les champs personnalisés.

Les champs d'exécution sont des champs qui sont évalués au moment de la requête. Ils vous permettent de créer de nouveaux champs à la volée sans devoir réindexer vos données. Nous pouvons définir des champs d'exécution sur l'index .kibana_alerting_cases afin d'utiliser un script simple pour analyser le tableau cases.custom_fields et extraire les valeurs dont nous avons besoin dans de nouveaux champs facilement interrogeables.

Pour ce flux de travail, nous allons créer deux champs d'exécution qui correspondront aux champs personnalisés créés ci-dessus :
* TuningRequired: Un champ booléen qui sera true si la bascule "Open tuning request" est activée.
* TuningDetail: Un champ de texte qui contiendra les commentaires de l'analyste dans le champ "Tuning request detail".

Avant de pouvoir créer les champs d'exécution, nous devons d'abord identifier l'identifiant unique (key) que Kibana attribue à chaque champ personnalisé. Actuellement, il n'existe pas de moyen direct de visualiser cet identifiant dans l'interface utilisateur. Pour le trouver, nous avons utilisé la solution de contournement suivante :

  1. Créez les champs. Si vous utilisez d'autres champs personnalisés, vous devez les créer un par un afin de faciliter l'identification des nouvelles clés de champ. Si vous n'avez que les deux champs mentionnés ci-dessus, vous pouvez les différencier en utilisant la valeur type qui peut être du texte ou une bascule.
  2. Créez un nouveau cas. Après avoir ajouté le champ, nous avons créé un cas de test dans Kibana, ajouté des données au champ de description et activé le champ de réglage obligatoire sur true, tous les autres champs personnalisés étant réglés sur false ou blank.
  3. Examinez le dossier. Nous avons ensuite navigué vers Discover et interrogé l'index .kibana_alerting_cases pour trouver le document correspondant à la nouvelle affaire. En inspectant le tableau cases.customFields dans la source du document, nous avons pu trouver le key associé à notre nouveau champ personnalisé. Enregistrez les valeurs des champs key à utiliser dans les scripts d'exécution.

Les données de cases.customFields sont formatées comme suit :

  [
    {
      "key": "4537b921-3ca4-4ff0-aa39-02dd6a3177bd",
      "type": "text",
      "value": "This alert is too noisy"
    },
    {
      "key": "cdf28896-c793-43d2-9384-99562e23a646",
      "type": "toggle",
      "value": true
    }
  ]

Création des champs d'exécution

Vous pouvez ajouter des champs d'exécution via l'interface utilisateur Kibana ou en utilisant l'API Elasticsearch dans la console Dev Tools. Si vous n'avez pas encore créé une vue de données pour les informations sur les cas, vous devrez d'abord le faire.

Dans la nouvelle vue Kibana Cases Data, cliquez sur le bouton "Add Field" (Ajouter un champ) pour ouvrir le menu déroulant et créer un nouveau champ d'exécution.

Entrez le nom du champ, dans cet exemple nous configurons TuningRequired comme un nouveau type de champ booléen. Cliquez sur le bouton "Définir la valeur" pour configurer ce champ comme un nouveau champ Runtime configuré par un script simple. Mettez à jour ce script sans effort pour remplacer TUNING_REQUIRED_FIELD_KEY_UUID par la valeur key du champ personnalisé Tuning Required et collez-la dans le champ de valeur, puis enregistrez le nouveau champ d'exécution.

...
    if (params._source.containsKey('cases') &&
    params._source.cases != null &&
    params._source.cases.containsKey('customFields') &&
    params._source.cases.customFields != null) 
{
  for (def cf : params._source.cases.customFields) {
    if (cf != null &&
        cf.containsKey('key') &&
        cf.key != null &&
        cf.key.contains('TUNING_REQUIRED_FIELD_KEY_UUID') &&
        cf.containsKey('value') &&
        cf.value != null) {
      emit(cf.value);
      break;
    }
  }
}

Répétez ce processus pour le champ TuningDetail. N'oubliez pas d'utiliser la valeur key du champ texte dans le script sans douleur de ce champ. Si vous avez d'autres champs personnalisés dans vos dossiers que vous souhaitez utiliser pour des tableaux de bord ou des mesures, vous pouvez les mapper de la même manière.

Si vous contrôlez vos paramètres de cluster et vos vues de données "en tant que code", vous pouvez également ajouter des champs d'exécution à un mappage d'index à l'aide de l'API de mise à jour de mappage depuis la console Kibana Dev Tools.

Automatiser la création des demandes d'accord

Nous pouvons déclencher cette automatisation de deux manières : par le biais d'une règle de détection personnalisée (qui créera une nouvelle alerte et l'enverra à un connecteur lorsqu'un cas est mis à jour avec une demande de réglage) ou par le biais d'une automatisation externe programmée qui interroge l'API.

Cette automatisation peut être créée à l'aide de n'importe quelle plateforme d'automatisation telle que Tines, Github Actions ou des scripts personnalisés. C'est la logique que nous utilisons pour notre automatisation :

Étape 1 : Recherchez tous les cas récemment étiquetés comme TuningRequired

Vous pouvez utiliser cette requête elasticsearch pour trouver tous les cas qui ont été mis à jour au cours de la dernière heure et pour lesquels le champ TuningRequired a été défini comme true. Cette requête utilise le champ cases.updated_at comme intervalle de temps. Les mappages de champs d'exécution doivent être inclus dans la demande d'API pour interroger les champs personnalisés.

Cette requête renvoie tous les documents de l'index .kibana_alerting_cases qui ont été mis à jour au cours de la dernière heure et dont le champ TuningRequired a été défini comme suit true

POST /.kibana_alerting_cases/_search  
{  
  "query": {  
    "bool": {  
      "must": [],  
      "filter": [  
        {  
          "bool": {  
            "should": [  
              {  
                "match": {  
                  "TuningRequired": true  
                }  
              }  
            ],  
            "minimum_should_match": 1  
          }  
        },  
        {  
          "range": {  
            "cases.updated_at": {  
              "format": "strict_date_optional_time",  
              "gte": "now-1h",  
              "lte": "now"  
            }  
          }  
        }  
      ],  
      "should": [],  
      "must_not": []  
    }  
  },  
 "runtime_mappings": {  
   "TuningDetail": {  
     "type": "keyword",  
     "script": {  
       "source": "if (\nparams._source.containsKey('cases') &&\nparams._source.cases != null &&\nparams._source.cases.containsKey('customFields') &&\nparams._source.cases.customFields != null\n) {\nfor (def cf : params._source.cases.customFields) {\nif (\ncf != null &&\ncf.containsKey('key') &&\ncf.key != null &&\ncf.key.contains('6cadc70a-7d68-4531-9861-7d5bc24c4c1c') &&\ncf.containsKey('value') &&\ncf.value != null\n) {\nemit(cf.value);\nbreak;\n}\n}\n}"  
     }  
   },  
   "TuningRequired": {  
     "type": "boolean",  
     "script": {  
       "source": "if (\nparams._source.containsKey('cases') &&\nparams._source.cases != null &&\nparams._source.cases.containsKey('customFields') &&\nparams._source.cases.customFields != null\n) {\nfor (def cf : params._source.cases.customFields) {\nif (\ncf != null &&\ncf.containsKey('key') &&\ncf.key != null &&\ncf.key.contains('496e71f2-2bce-47a2-93a8-00db0de2d1b4') &&\ncf.containsKey('value') &&\ncf.value != null\n) {\nemit(cf.value);\nbreak;\n}\n}\n}"  
     }  
   }  
 },  
  "fields": [  
    "TuningDetail",  
    "TuningRequired"  
  ]  
}

Chaque fois qu'un champ est modifié ou qu'un commentaire est fait dans un cas, le champ updated_at est mis à jour à l'heure actuelle. Comme toute mise à jour ou tout commentaire ajouté à un cas met à jour cet horodatage, il est possible qu'un même cas soit renvoyé plusieurs fois par cette automatisation si elle est exécutée régulièrement pendant que le cas est mis à jour. Tout processus d'automatisation utilisé à cette fin doit comporter un processus de déduplication afin d'éviter de traiter le même cas plusieurs fois dans ce scénario.

Étape 2 : Analyse de chaque cas

Passez en boucle sur chacun des cas renvoyés par la requête précédente pour les traiter un par un. Chaque document renvoyé contiendra le tableau fields avec les valeurs des champs personnalisés, ainsi que d'autres champs utiles. Analysez chacun des champs suivants et stockez-les en vue d'une utilisation ultérieure :

  • Le champ _id aura un format tel que cases:{{case_ID}}. L'identifiant du cas est utilisé pour les futures requêtes API dans l'automatisation afin d'ajouter des commentaires au cas ou de récupérer toutes les alertes liées au cas.
  • cases.title est le titre de l'affaire
  • cases.assignees est la personne à qui le dossier est attribué
  • cases.updated_by est la dernière personne à avoir mis à jour le dossier, il s'agit souvent de la personne qui soumet la demande d'accord et cela peut être utile pour savoir qui contacter pour plus d'informations.
  • cases.tags peut être utile si vous utilisez des balises pour trier ou identifier vos cas.

Étape 3 : Récupération des alertes liées au dossier

Pour chaque cas, vous voudrez savoir quelles alertes sont liées au cas afin de savoir quelles alertes doivent être réglées. Vous pouvez le faire en utilisant l'API des cas avec le champ _id pour le cas.

/api/cases/{caseId}/alerts

Cette requête renvoie un tableau de toutes les valeurs d'alerte id qui sont attachées au cas. En utilisant cette valeur ID, vous pouvez interroger l'index elasticsearch de .siem-signals* pour trouver les informations complètes sur chaque alerte liée à l'affaire qui doit être réglée.

POST /.siem-signals-*/_search  
{  
 "size": 1,  
 "query": {  
   "bool": {  
     "must": [],  
     "filter": [  
       {  
         "bool": {  
           "should": [  
             {  
               "match": {  
                 "_id": "{{alert_id}}"  
               }  
             }  
           ],  
           "minimum_should_match": 1  
         }  
       },  
       {  
         "range": {  
           "@timestamp": {  
             "format": "strict_date_optional_time",  
             "gte": "now-30d",  
             "lte": "now"  
           }  
         }  
       }  
     ],  
     "should": [],  
     "must_not": []  
   }  
 }  
}

À partir des résultats de cette requête, vous pouvez extraire des informations sur le signalement, telles que le nom et la date de création, ainsi que toute autre information susceptible d'aider à la mise au point, comme les champs user.name ou process.name. Étant donné qu'un cas peut être associé à plusieurs alertes, vous voudrez dédupliquer les alertes en fonction de la valeur signal.rule.name.

Étape 4 : Ouverture d'une demande d'accord.

Cette étape dépend du système de billetterie que vous utilisez dans votre environnement. Notre équipe utilise github issues pour suivre les demandes d'accord et slack pour les notifications, mais cela pourrait également être fait avec n'importe quel système de ticketing ou de gestion de projet qui prend en charge l'automatisation.

Voici le flux logique que nous utilisons pour notre automatisation en utilisant à la fois Github et Slack pour suivre les demandes de mise au point :

  • En utilisant le nom de l'alerte, nous recherchons toutes les demandes d'accord ouvertes existantes.
    • Si une demande d'accord existe déjà, nous la mettons à jour avec les détails de l'affaire et de la nouvelle demande.
    • S'il n'existe pas de demande existante, nous ouvrons une nouvelle demande d'accord et y joignons les informations nécessaires.
  • Nous envoyons ensuite une notification slack au canal slack de l'équipe d'ingénierie de détection contenant un lien vers la demande de réglage, un lien vers le cas et des détails sur la demande et l'alerte.
  • Nous utilisons ensuite l'API des cas pour ajouter un commentaire au cas original avec un lien vers la question de la demande d'accord.
  • Agent d'intelligence artificielle en option: Nous commençons à expérimenter l'utilisation d'agents d'intelligence artificielle pour analyser les alertes et les informations relatives aux cas, puis fournir un contexte encore plus précis avec la demande de réglage, voire recommander les modifications à apporter aux règles de détection.

Le résultat final de cette automatisation est que nos analystes SOC peuvent créer un ticket de demande de réglage de détection détaillé en un seul clic à partir de leur dossier. Nous avons constaté une augmentation spectaculaire de la réduction des faux positifs et de l'efficacité globale de nos règles de détection grâce à cette automatisation.

Conclusion

En utilisant les cas Kibana avec des champs personnalisés et en intégrant des plateformes d'automatisation, vous pouvez optimiser un grand nombre de vos processus manuels. Ce flux de travail automatisé réduit la charge manuelle associée à la collecte des commentaires des analystes, garantissant ainsi que les précieux commentaires des analystes se traduisent rapidement par des améliorations exploitables des règles de détection. Il en résulte un SOC plus efficace, plus précis et plus résistant, capable de s'adapter rapidement aux nouvelles menaces et de réduire la fatigue liée aux alertes.

Prêt à optimiser l'efficacité de votre SOC et à améliorer votre posture de détection ? Découvrez Elastic Security et commencez dès aujourd'hui à créer vos propres flux de demandes de réglage automatisés !

Partager cet article