Collecter les journaux de sécurité ServiceNow

Compatible avec :

Ce document explique comment envoyer des événements de sécurité ServiceNow à Google Security Operations à l'aide d'un flux de webhook. L'analyseur de sécurité ServiceNow est conçu pour les événements de sécurité ServiceNow Instance Security Center, tels que les échecs de connexion, les connexions SNC, les connexions administrateur, l'usurpation d'identité et l'élévation de sécurité (voir Événements de sécurité ServiceNow Instance Security Center). Une intégration ServiceNow publie chaque événement au format JSON sur un point de terminaison de webhook Google SecOps, où l'analyseur le normalise au modèle de données unifié (UDM).

L'analyseur reconnaît cinq valeurs d'événement : Failed Login, Admin Login, SNC Login, Impersonation et Security Elevation. Chaque valeur correspond à un événement ServiceNow enregistré dans la file d'attente sysevent. Ce document crée un flux de webhook, un Script Include qui publie sur le flux et quatre actions de script qui se déclenchent sur les enregistrements sysevent correspondants et appellent le Script Include.

Une fois cette configuration unique effectuée, ServiceNow transfère automatiquement chaque nouvel événement de sécurité à Google SecOps. Aucune autre action n'est requise de la part de l'administrateur.

Avant de commencer

Assurez-vous de remplir les conditions préalables suivantes :

  • Une instance Google SecOps.
  • Une instance ServiceNow avec un compte utilisateur disposant du rôle admin ou des droits d'accès à Définition du système > Inclure des scripts, Propriétés du système, Politique système > Événements > Actions de script et Registre.
  • Une instance ServiceNow existante avec Security Center activé. ISC n'est plus disponible à la vente et ne peut pas être activé sur de nouvelles instances.
  • Accès privilégié à la console Google Google Cloud (pour la création de clés API).

Créer un flux de webhook dans Google SecOps

Les sections suivantes expliquent comment créer un flux de webhook dans Google SecOps.

Créer le flux

  1. Accédez à Paramètres SIEM> Flux.
  2. Cliquez sur Add New Feed (Ajouter un flux).
  3. Sur la page suivante, cliquez sur Configurer un seul flux.
  4. Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple, ServiceNow Security Events).
  5. Sélectionnez Webhook comme type de source.
  6. Sélectionnez ServiceNow Security comme type de journal.
  7. Cliquez sur Suivant.
  8. Spécifiez les valeurs des paramètres d'entrée suivants :

    • Délimiteur de fractionnement : saisissez \n lorsque l'intégration envoie plusieurs événements JSON par requête. Laissez ce champ vide si chaque requête contient un seul événement.
    • Espace de noms de l'élément : espace de noms de l'élément.
    • Libellés d'ingestion : libellé appliqué aux événements de ce flux.
  9. Cliquez sur Suivant.

  10. Vérifiez la configuration de votre nouveau flux sur l'écran Finaliser, puis cliquez sur Envoyer.

Générer et enregistrer la clé secrète

  1. Sur la page d'informations sur le flux, cliquez sur Générer une clé secrète.
  2. Copiez et enregistrez la clé secrète dans un emplacement sécurisé.

Obtenir l'URL du point de terminaison du flux

  1. Accédez à l'onglet Détails du flux.
  2. Dans la section Endpoint Information (Informations sur le point de terminaison), copiez l'URL du point de terminaison du flux. Le format d'URL est le suivant :

    https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    

    ou, pour un point de terminaison régional :

    https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    
  3. Enregistrez cette URL pour une étape ultérieure.

  4. Cliquez sur OK.

Créer une clé API Google Cloud

  1. Accédez à la page Identifiants de la console Google Google Cloud .
  2. Sélectionnez le projet associé à votre instance Google SecOps.
  3. Cliquez sur Créer des identifiants> Clé API.
  4. Cliquez sur Modifier la clé API pour la restreindre.
  5. Dans le champ Nom, saisissez un nom descriptif (par exemple, ServiceNow Webhook API Key).
  6. Sous Restrictions relatives aux API :

    1. Sélectionnez Restreindre la clé.
    2. Dans la liste Sélectionner des API, sélectionnez API Google SecOps.
  7. Cliquez sur Enregistrer.

  8. Copiez la clé API et enregistrez-la dans un endroit sûr.

Stocker les identifiants Google SecOps dans ServiceNow

Stockez l'URL du point de terminaison et les identifiants en tant que propriétés système ServiceNow afin que le code d'intégration ne contienne pas de secrets.

  1. Dans ServiceNow, accédez à Propriétés système > sys_properties.list.
  2. Cliquez sur Nouveau et fournissez les informations de configuration suivantes :

    • Nom : x_chronicle.endpoint_url
    • Valeur : collez l'URL du point de terminaison du flux.
    • Type : string
  3. Cliquez sur Envoyer.

  4. Cliquez sur Nouveau et fournissez les informations de configuration suivantes :

    • Nom : x_chronicle.api_key
    • Valeur : collez la clé API Google Cloud .
    • Type : password2
  5. Cliquez sur Envoyer.

  6. Cliquez sur Nouveau et fournissez les informations de configuration suivantes :

    • Nom : x_chronicle.secret_key
    • Valeur : collez la clé secrète du flux Google SecOps.
    • Type : password2
  7. Cliquez sur Envoyer.

Créer l'inclusion de script utilitaire de webhook

Cette inclusion de script publie une charge utile JSON sur le point de terminaison du webhook Google SecOps à l'aide de l'API à portée sn_ws.RESTMessageV2 de ServiceNow. La clé API et la clé secrète sont envoyées en tant qu'en-têtes HTTP.

  1. Accédez à Définition du système> Inclure les scripts.
  2. Cliquez sur New (Nouveau).
  3. Fournissez les informations de configuration suivantes :

    • Nom : ChronicleWebhookUtil
    • Nom de l'API : ChronicleWebhookUtil
    • Client callable (Appelable par le client) : décochez la case
    • Actif : coché
  4. Dans le champ Script, saisissez le code suivant :

    var ChronicleWebhookUtil = Class.create();
    ChronicleWebhookUtil.prototype = {
        initialize: function() {
            this.endpointURL = gs.getProperty('x_chronicle.endpoint_url');
            this.apiKey = gs.getProperty('x_chronicle.api_key');
            this.secretKey = gs.getProperty('x_chronicle.secret_key');
        },
    
        // payload: a plain object whose keys match the required JSON contract.
        sendEvent: function(payload) {
            try {
                if (!this.endpointURL || !this.apiKey || !this.secretKey) {
                    gs.error('[Chronicle] Missing configuration. Check System Properties: x_chronicle.*');
                    return false;
                }
    
                var request = new sn_ws.RESTMessageV2();
                request.setEndpoint(this.endpointURL);
                request.setHttpMethod('POST');
                request.setRequestHeader('Content-Type', 'application/json');
                request.setRequestHeader('X-goog-api-key', this.apiKey);
                request.setRequestHeader('X-Webhook-Access-Key', this.secretKey);
                request.setRequestBody(JSON.stringify(payload));
    
                var response = request.execute();
                var statusCode = response.getStatusCode();
    
                if (statusCode == 200 || statusCode == 201 || statusCode == 204) {
                    gs.info('[Chronicle] Event sent: ' + payload.event + ' | Status: ' + statusCode);
                    return true;
                }
    
                gs.error('[Chronicle] Failed to send event: ' + payload.event + ' | Status: ' + statusCode + ' | Response: ' + response.getBody());
                return false;
            } catch (ex) {
                gs.error('[Chronicle] Exception sending event: ' + ex.message);
                return false;
            }
        },
    
        type: 'ChronicleWebhookUtil'
    };
    
  5. Cliquez sur Envoyer.

Vérifier le registre des événements

Une action de script ne se déclenche que si son nom d'événement existe dans la table Event Registry (sysevent_register). ServiceNow fournit les cinq événements utilisés par cette intégration prêts à l'emploi. Toutefois, il est préférable de vérifier, car une entrée manquante ne génère aucune erreur et l'action de script ne s'exécute jamais.

  1. Dans ServiceNow, accédez à System Policy> Events> Registry (sysevent_register.list).
  2. Filtrez la colonne Nom de l'événement pour chacune des entrées suivantes et vérifiez qu'un enregistrement existe :

    • login
    • login.failed
    • impersonation.start
    • security.elevated_role.enabled
  3. Si une entrée est manquante, cliquez sur Nouveau, définissez le champ Nom de l'événement sur la valeur manquante, définissez Table sur Global [global], puis cliquez sur Envoyer.

Créer les actions de script

Chaque action de script s'abonne à un nom d'événement ServiceNow. Lorsque ServiceNow insère un enregistrement correspondant dans la file d'attente sysevent, l'action de script s'exécute, lit les paramètres d'événement et appelle ChronicleWebhookUtil pour publier la charge utile.

L'analyseur est associé aux événements ServiceNow suivants :

Valeur event de l'analyseur Nom de l'événement ServiceNow Déclencheur
Failed Login login.failed Échec de la tentative de connexion (quelle que soit la méthode d'authentification).
Admin Login login Connexion réussie d'un utilisateur disposant du rôle admin.
SNC Login login Connexion réussie d'un utilisateur disposant du rôle snc_external.
Impersonation impersonation.start Un administrateur commence à se faire passer pour un autre utilisateur.
Security Elevation security.elevated_role.enabled Un utilisateur passe au rôle security_admin ou à un autre rôle à privilèges élevés.

login et login.failed définissent parm1 sur le nom d'utilisateur et parm2 sur l'adresse IP source. Les autres événements suivent la même convention parm1/parm2, mais leur contenu exact dépend de votre version de ServiceNow. Ouvrez l'entrée de registre de chaque événement et vérifiez que la description des paramètres correspond au script décrit plus loin. Ajustez les références parm1 ou parm2 si votre registre est différent.

Créer l'action de script d'échec de connexion

  1. Accédez à System Policy > Events > Script Actions (Règles système > Événements > Actions de script).
  2. Cliquez sur New (Nouveau).
  3. Fournissez les informations de configuration suivantes :

    • Nom : Chronicle - Failed Login
    • Nom de l'événement : login.failed
    • Actif : coché
  4. Dans le champ Script, saisissez le code suivant :

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        new ChronicleWebhookUtil().sendEvent({
            event: 'Failed Login',
            event_created: event.sys_created_on.getValue(),
            user: event.parm1.toString(),
            ip_address: event.parm2.toString()
        });
    })(current, event);
    
  5. Cliquez sur Envoyer.

Créer l'action de script de connexion

Cette action de script se déclenche à chaque connexion réussie et transmet l'enregistrement uniquement lorsque l'utilisateur connecté possède le rôle admin ou snc_external. Le champ event est défini en conséquence.

  1. Accédez à System Policy > Events > Script Actions (Règles système > Événements > Actions de script).
  2. Cliquez sur New (Nouveau).
  3. Fournissez les informations de configuration suivantes :

    • Nom : Chronicle - Login
    • Nom de l'événement : login
    • Actif : coché
  4. Dans le champ Script, saisissez le code suivant :

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        var userName = event.parm1.toString();
        var ipAddress = event.parm2.toString();
    
        var user = new GlideRecord('sys_user');
        if (!user.get('user_name', userName)) {
            return;
        }
    
        function hasRole(roleName) {
            var role = new GlideRecord('sys_user_has_role');
            role.addQuery('user', user.sys_id);
            role.addQuery('role.name', roleName);
            role.query();
            return role.next();
        }
    
        var eventValue;
        if (hasRole('snc_external')) {
            eventValue = 'SNC Login';
        } else if (hasRole('admin')) {
            eventValue = 'Admin Login';
        } else {
            return;
        }
    
        new ChronicleWebhookUtil().sendEvent({
            event: eventValue,
            event_created: event.sys_created_on.getValue(),
            user: userName,
            ip_address: ipAddress
        });
    })(current, event);
    
  5. Cliquez sur Envoyer.

Créer l'action de script d'emprunt d'identité

  1. Accédez à System Policy > Events > Script Actions (Règles système > Événements > Actions de script).
  2. Cliquez sur New (Nouveau).
  3. Fournissez les informations de configuration suivantes :

    • Nom : Chronicle - Impersonation
    • Nom de l'événement : impersonation.start
    • Actif : coché
  4. Dans le champ Script, saisissez le code suivant :

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        new ChronicleWebhookUtil().sendEvent({
            event: 'Impersonation',
            event_created: event.sys_created_on.getValue(),
            user: event.parm1.toString(),       // impersonator
            snc_user: event.parm2.toString()    // impersonated user
        });
    })(current, event);
    
  5. Cliquez sur Envoyer.

Créer l'action de script d'élévation de sécurité

  1. Accédez à System Policy > Events > Script Actions (Règles système > Événements > Actions de script).
  2. Cliquez sur New (Nouveau).
  3. Fournissez les informations de configuration suivantes :

    • Nom : Chronicle - Security Elevation
    • Nom de l'événement : security.elevated_role.enabled
    • Actif : coché
  4. Dans le champ Script, saisissez le code suivant :

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        new ChronicleWebhookUtil().sendEvent({
            event: 'Security Elevation',
            event_created: event.sys_created_on.getValue(),
            user: event.parm1.toString()
        });
    })(current, event);
    
  5. Cliquez sur Envoyer.

Valider l'intégration

Utilisez l'une des approches suivantes.

Valider à l'aide d'un événement synthétique

Pour tester chaque action de script immédiatement sans attendre un véritable événement de sécurité, procédez comme suit pour mettre l'événement en file d'attente à partir d'un script d'arrière-plan :

  1. Dans ServiceNow, accédez à System Definition > Scripts - Background (Définition du système > Scripts - Arrière-plan).
  2. Dans le champ Exécuter le script, saisissez l'une des lignes suivantes, puis cliquez sur Exécuter le script :

    gs.eventQueue('login.failed', null, 'test.user', '203.0.113.45');
    gs.eventQueue('login', null, 'admin', '203.0.113.45');
    gs.eventQueue('impersonation.start', null, 'admin', 'test.user');
    gs.eventQueue('security.elevated_role.enabled', null, 'admin', 'security_admin');
    
  3. Patientez jusqu'à une minute pour que le job Event Manager traite la file d'attente.

Valider à l'aide d'un événement réel

Pour vérifier l'intégration, générez l'un des événements de sécurité mappés suivants dans ServiceNow :

  • Échec de la connexion : ouvrez /login.do dans une fenêtre de navigation privée et saisissez un mot de passe incorrect.
  • Connexion administrateur : connectez-vous avec un utilisateur disposant du rôle admin à partir d'une adresse IP différente de celle que vous utilisez habituellement.
  • Usurpation d'identité : empruntez l'identité d'un autre utilisateur depuis un compte administrateur.
  • Élévation de sécurité : passez au rôle security_admin à partir d'un utilisateur disposant du rôle admin.

Confirmer le transfert

  1. Dans ServiceNow, accédez à Stratégie système> Événements> Journal des événements (sysevent.list), puis vérifiez qu'un enregistrement portant le nom d'événement correspondant s'affiche.
  2. Dans ServiceNow, accédez à Journaux système > Journal système > Tous et vérifiez qu'un message d'information [Chronicle] Event sent: ... s'affiche avec l'état 200, 201 ou 204. Un message [Chronicle] Failed to send event ou [Chronicle] Exception sending event indique un problème d'identifiants ou de connectivité.
  3. Dans Google SecOps, exécutez une recherche UDM pour metadata.vendor_name = "SERVICENOW" et metadata.product_name = "SERVICENOW_SECURITY".
  4. Vérifiez que l'événement s'affiche avec metadata.event_type défini sur USER_LOGIN ou USER_CHANGE_PERMISSIONS, et que principal.user.userid est renseigné.

Référence des méthodes d'authentification

Les flux de webhook Google SecOps acceptent la clé API et la clé secrète en tant qu'en-têtes HTTP ou paramètres de requête d'URL. Ce guide utilise la méthode des en-têtes, car sn_ws.RESTMessageV2 est compatible avec les en-têtes personnalisés, ce qui permet de conserver les identifiants en dehors des URL et des journaux d'accès au serveur.

En-têtes utilisés dans ce guide :

  • X-goog-api-key : clé API Google Cloud pour l'API Google SecOps.
  • X-Webhook-Access-Key : clé secrète du flux générée par Google SecOps.

Si une intégration ne peut pas envoyer d'en-têtes personnalisés, ajoutez plutôt les identifiants à l'URL du point de terminaison :

<ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>

Limites et bonnes pratiques concernant les webhooks

Limite Valeur
Taille maximale de la requête 4 Mo
RPS (requêtes par seconde) max. 15 000
Délai avant expiration de la requête 30 seconds
Comportement de nouvelle tentative Automatique avec intervalle exponentiel entre les tentatives

Pour contrôler le volume, n'envoyez que les événements de sécurité dont vos détections ont besoin et regroupez plusieurs événements par requête avec le délimiteur de fractionnement \n lorsque la source produit des événements par rafales.

Pour en savoir plus sur les flux Google SecOps, consultez la documentation sur les flux Google SecOps. Pour en savoir plus sur les exigences associées à chaque type de flux, consultez Configuration des flux par type.

Si vous rencontrez des problèmes lors de la création de flux, contactez l'assistance Google SecOps.

Table de mappage UDM

Champ du journal Mappage UDM Logique
event extensions.auth.type Mappé : "Failed Login", "SNC Login", "Admin Login", "Impersonation"MACHINE
event_created metadata.event_timestamp Analysé en tant que yyyy-MM-dd HH:mm:ss
event_type metadata.event_type Renommé/Mappé
event metadata.product_event_type Mappé lorsque event != ``
ip_address principal.ip Fusionné
user principal.user.userid Mappé lorsque user != ``
created_by target.user.userid Mappé lorsque created_by != ``
snc_user target.user.userid Mappé lorsque snc_user != ``
timestamp event1.idm.read_only_udm.metadata.event_timestamp Mappé à partir du journal des modifications
data.sys_id event1.idm.read_only_udm.metadata.product_log_id Mappé à partir du journal des modifications
data.message_data event1.idm.read_only_udm.metadata.description Mappé à partir du journal des modifications
data.source event1.idm.read_only_udm.principal.resource.name Mappé à partir du journal des modifications
source event1.idm.read_only_udm.additional.fields Mappé à partir du journal des modifications
data.sys_created_on event1.idm.read_only_udm.metadata.collected_timestamp Mappé à partir du journal des modifications
data.sys_created_by event1.idm.read_only_udm.principal.user.userid Mappé à partir du journal des modifications
data.user event1.idm.read_only_udm.principal.user.userid Mappé à partir du journal des modifications
source_instance event1.idm.read_only_udm.principal.namespace Mappé à partir du journal des modifications
data.role event1.idm.read_only_udm.target.resource.attribute.roles Mappé à partir du journal des modifications
data.granted_by event1.idm.read_only_udm.target.user.userid Mappé à partir du journal des modifications
data.level event1.idm.read_only_udm.security_result.severity Mappé à partir du journal des modifications
data.state event1.idm.read_only_udm.security_result.action_details Mappé à partir du journal des modifications

Journal des modifications

Afficher le journal des modifications pour ce parseur

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