Raccogliere i log WAF di Signal Sciences

Supportato in:

Questo documento spiega come importare i log WAF di Signal Sciences in Google Security Operations utilizzando Google Cloud Storage. Il parser trasforma i log di Signal Sciences dal formato JSON nel modello Unified Data Model (UDM) di Chronicle. Gestisce due strutture di messaggi principali: i messaggi "RPC.PreRequest/PostRequest" vengono analizzati utilizzando i pattern Grok, mentre gli altri messaggi vengono elaborati come oggetti JSON, estraendo i campi pertinenti e mappandoli allo schema UDM.

Prima di iniziare

Assicurati di soddisfare i seguenti prerequisiti:

  • Istanza Google SecOps
  • Il flusso VPC è configurato e attivo nel tuo ambiente Google Cloud
  • Accesso con privilegi al WAF di Signal Sciences

Crea un Google Cloud bucket di archiviazione

  1. Accedi alla Google Cloud console.
  2. Vai alla pagina Bucket Cloud Storage.

    Vai a Bucket

  3. Fai clic su Crea.

  4. Nella pagina Crea un bucket, inserisci le informazioni del bucket. Dopo ogni passaggio riportato di seguito, fai clic su Continua per passare al passaggio successivo:

    1. Nella sezione Inizia:

      • Inserisci un nome univoco che soddisfi i requisiti per il nome del bucket (ad esempio, vpcflow-logs).
      • Per attivare lo spazio dei nomi gerarchico, fai clic sulla freccia di espansione per espandere la sezione Ottimizza per workload orientati ai file e con uso intensivo dei dati, poi seleziona Abilita uno spazio dei nomi gerarchico in questo bucket.
      • Per aggiungere un'etichetta del bucket, fai clic sulla freccia di espansione per espandere la sezione Etichette.
      • Fai clic su Aggiungi etichetta e specifica una chiave e un valore per l'etichetta.
    2. Nella sezione Scegli dove archiviare i tuoi dati, segui questi passaggi:

      • Seleziona un Tipo di località.
      • Utilizza il menu del tipo di località per selezionare una località in cui verranno archiviati in modo permanente i dati degli oggetti all'interno del bucket.
      • Per configurare la replica tra bucket, espandi la sezione Configura replica tra bucket.
    3. Nella sezione Scegli una classe di archiviazione per i tuoi dati, seleziona una classe di archiviazione predefinita per il bucket oppure Autoclass per la gestione automatica della classe di archiviazione dei dati del bucket.

    4. Nella sezione Scegli come controllare l'accesso agli oggetti, seleziona No per applicare la prevenzione dell'accesso pubblico e seleziona un modello di controllo dell'accesso per gli oggetti del bucket.

    5. Nella sezione Scegli come proteggere i dati degli oggetti, segui questi passaggi:

      • Seleziona una delle opzioni in Protezione dei dati che vuoi impostare per il bucket.
      • Per scegliere come criptare i dati degli oggetti, fai clic sulla freccia di espansione con l'etichetta Crittografia dei dati e seleziona un metodo di crittografia dei dati.
  5. Fai clic su Crea.

Configurare una chiave API WAF di Signal Sciences

  1. Accedi alla UI web di Signal Sciences WAF.
  2. Vai a Il mio profilo > Token di accesso API.
  3. Fai clic su Aggiungi token di accesso all'API.
  4. Fornisci un nome univoco e descrittivo (ad esempio, Google SecOps).
  5. Fai clic su Crea token di accesso API.
  6. Copia e salva il token in un luogo sicuro.
  7. Fai clic su Ho capito per completare la creazione del token.

Esegui il deployment di uno script su un host Linux per estrarre i log da Signal Sciences e archiviarli in Google Cloud

  1. Accedi all'host Linux utilizzando SSH.
  2. Installa la libreria Python per archiviare il file JSON del WAF Signal Sciences in un bucket Cloud Storage:

    pip install google-cloud-storage
    
  3. Imposta questa variabile di ambiente per chiamare il file JSON contenente le credenziali da Google Cloud:

    export GOOGLE_APPLICATION_CREDENTIALS="path/to/your/service-account-key.json"
    
  4. Configura le seguenti variabili di ambiente perché queste informazioni non devono essere codificate in modo permanente:

    export SIGSCI_EMAIL=<Signal_Sciences_account_email>
    export SIGSCI_TOKEN=<Signal_Sciences_API_token>
    export SIGSCI_CORP=<Corporation_name_in_Signal_Sciences>
    
  5. Esegui questo script:

    import sys
    import requests
    import os
    import calendar
    import json
    from datetime import datetime, timedelta
    from google.cloud import storage
    
    # Check if all necessary environment variables are set
    
    if 'SIGSCI_EMAIL' not in os.environ or 'SIGSCI_TOKEN' not in os.environ or 'SIGSCI_CORP' not in os.environ:
    print("ERROR: You need to define SIGSCI_EMAIL, SIGSCI_TOKEN, and SIGSCI_CORP environment variables.")
    print("Please fix and run again. Existing...")
    sys.exit(1)  # Exit if environment variables are not set
    
    # Define the Google Cloud Storage bucket name and output file name
    
    bucket_name = 'Your_GCS_Bucket'  # Replace with your GCS bucket name
    output_file_name = 'signal_sciences_logs.json'
    
    # Initialize Google Cloud Storage client
    
    storage_client = storage.Client()
    
    # Function to upload data to Google Cloud Storage
    
    def upload_to_gcs(bucket_name, data, destination_blob_name):
        bucket = storage_client.bucket(bucket_name)
        blob = bucket.blob(destination_blob_name)
        blob.upload_from_string(data, content_type='application/json')
        print(f"Data uploaded to {destination_blob_name} in bucket {bucket_name}")
    
    # Signal Sciences API information
    
    api_host = 'https://dashboard.signalsciences.net'
    # email = 'user@domain.com'  # Signal Sciences account email
    # token = 'XXXXXXXX-XXXX-XXX-XXXX-XXXXXXXXXXXX'  # API token for authentication
    # corp_name = 'Domain'  # Corporation name in Signal Sciences
    # site_names = ['testenv']  # Replace with your actual site names
    
    # List of comma-delimited sites that you want to extract data from
    
    site_names = [ 'site123', 'site345' ]        # Define all sites to pull logs from
    
    email = os.environ.get('SIGSCI_EMAIL')       # Signal Sciences account email
    token = os.environ.get('SIGSCI_TOKEN')       # API token for authentication
    corp_name = os.environ.get('SIGSCI_CORP')    # Corporation name in Signal Sciences
    
    # Calculate the start and end timestamps for the previous hour in UTC
    
    until_time = datetime.utcnow().replace(minute=0, second=0, microsecond=0)
    from_time = until_time - timedelta(hours=1)
    until_time = calendar.timegm(until_time.utctimetuple())
    from_time = calendar.timegm(from_time.utctimetuple())
    
    # Prepare HTTP headers for the API request
    
    headers = {
        'Content-Type': 'application/json',
        'x-api-user': email,
        'x-api-token': token
    }
    
    # Collect logs for each site
    
    collected_logs = []
    
    for site_name in site_names:
        url = f"{api_host}/api/v0/corps/{corp_name}/sites/{site_name}/feed/requests?from={from_time}&until={until_time}"
        while True:
            response = requests.get(url, headers=headers)
            if response.status_code != 200:
                print(f"Error fetching logs: {response.text}", file=sys.stderr)
                break
    
            # Parse the JSON response
    
            data = response.json()
            collected_logs.extend(data['data'])  # Add the log messages to our list
    
            # Pagination: check if there is a next page
    
            next_url = data.get('next', {}).get('uri')
            if not next_url:
                break
            url = api_host + next_url
    
    # Convert the collected logs to a newline-delimited JSON string
    
    json_data = '\n'.join(json.dumps(log) for log in collected_logs)
    
    # Save the newline-delimited JSON data to a GCS bucket
    
    upload_to_gcs(bucket_name, json_data, output_file_name)
    

    Configurare i feed

Esistono due diversi punti di accesso per configurare i feed nella piattaforma Google SecOps:

  • Impostazioni SIEM > Feed
  • Hub dei contenuti > Pacchetti di contenuti

Configura i feed da Impostazioni SIEM > Feed

Per configurare un feed:

  1. Vai a Impostazioni SIEM > Feed.
  2. Fai clic su Aggiungi nuovo feed.
  3. Nella pagina successiva, fai clic su Configura un singolo feed.
  4. Nel campo Nome feed, inserisci un nome per il feed (ad esempio, Signal Sciences WAF Logs).
  5. Seleziona Google Cloud Storage come Tipo di origine.
  6. Seleziona Signal Sciences WAF come Tipo di log.
  7. Fai clic su Ottieni account di servizio come Account di servizio Chronicle.
  8. Fai clic su Avanti.
  9. Specifica i valori per i seguenti parametri di input:

    • URI bucket di archiviazione: Google Cloud URL del bucket di archiviazione nel formato gs://my-bucket/<value>.
    • URI Is A: seleziona Directory which includes subdirectories (Directory che include sottodirectory).
    • Opzioni di eliminazione dell'origine: seleziona l'opzione di eliminazione in base alle tue preferenze.

  10. Fai clic su Avanti.

  11. Controlla la nuova configurazione del feed nella schermata Finalizza e poi fai clic su Invia.

Configurare i feed dall'hub dei contenuti

Specifica i valori per i seguenti campi:

  • URI bucket di archiviazione: Google Cloud URL del bucket di archiviazione nel formato gs://my-bucket/<value>.
  • URI Is A: seleziona Directory which includes subdirectories (Directory che include sottodirectory).
  • Opzioni di eliminazione dell'origine: seleziona l'opzione di eliminazione in base alle tue preferenze.

Opzioni avanzate

  • Nome feed: un valore precompilato che identifica il feed.
  • Tipo di origine: metodo utilizzato per raccogliere i log in Google SecOps.
  • Spazio dei nomi dell'asset: lo spazio dei nomi associato al feed.
  • Etichette di importazione: etichette applicate a tutti gli eventi di questo feed.

Tabella di mappatura UDM

Campo log Mappatura UDM Logic
CLIENT-IP target.ip Estratto dal campo di intestazione CLIENT-IP.
CLIENT-IP target.port Estratto dal campo di intestazione CLIENT-IP.
Connessione security_result.about.labels Il valore viene estratto dal campo Connection del log non elaborato e mappato a security_result.about.labels.
Content-Length security_result.about.labels Il valore viene estratto dal campo Content-Length del log non elaborato e mappato a security_result.about.labels.
Content-Type security_result.about.labels Il valore viene estratto dal campo Content-Type del log non elaborato e mappato a security_result.about.labels.
creato metadata.event_timestamp Il valore viene estratto dal campo created del log non elaborato e mappato a metadata.event_timestamp.
details.headersIn security_result.about.resource.attribute.labels Il valore viene estratto dal campo details.headersIn del log non elaborato e mappato a security_result.about.resource.attribute.labels.
details.headersOut security_result.about.resource.attribute.labels Il valore viene estratto dal campo details.headersOut del log non elaborato e mappato a security_result.about.resource.attribute.labels.
details.id principal.process.pid Il valore viene estratto dal campo details.id del log non elaborato e mappato a principal.process.pid.
details.method network.http.method Il valore viene estratto dal campo details.method del log non elaborato e mappato a network.http.method.
details.protocol network.application_protocol Il valore viene estratto dal campo details.protocol del log non elaborato e mappato a network.application_protocol.
details.remoteCountryCode principal.location.country_or_region Il valore viene estratto dal campo details.remoteCountryCode del log non elaborato e mappato a principal.location.country_or_region.
details.remoteHostname target.hostname Il valore viene estratto dal campo details.remoteHostname del log non elaborato e mappato a target.hostname.
details.remoteIP target.ip Il valore viene estratto dal campo details.remoteIP del log non elaborato e mappato a target.ip.
details.responseCode network.http.response_code Il valore viene estratto dal campo details.responseCode del log non elaborato e mappato a network.http.response_code.
details.responseSize network.received_bytes Il valore viene estratto dal campo details.responseSize del log non elaborato e mappato a network.received_bytes.
details.serverHostname principal.hostname Il valore viene estratto dal campo details.serverHostname del log non elaborato e mappato a principal.hostname.
details.serverName principal.asset.network_domain Il valore viene estratto dal campo details.serverName del log non elaborato e mappato a principal.asset.network_domain.
details.tags security_result.detection_fields Il valore viene estratto dal campo details.tags del log non elaborato e mappato a security_result.detection_fields.
details.tlsCipher network.tls.cipher Il valore viene estratto dal campo details.tlsCipher del log non elaborato e mappato a network.tls.cipher.
details.tlsProtocol network.tls.version Il valore viene estratto dal campo details.tlsProtocol del log non elaborato e mappato a network.tls.version.
details.userAgent network.http.user_agent Il valore viene estratto dal campo details.userAgent del log non elaborato e mappato a network.http.user_agent.
details.uri network.http.referral_url Il valore viene estratto dal campo details.uri del log non elaborato e mappato a network.http.referral_url.
eventType metadata.product_event_type Il valore viene estratto dal campo eventType del log non elaborato e mappato a metadata.product_event_type.
headersIn security_result.about.labels Il valore viene estratto dal campo headersIn del log non elaborato e mappato a security_result.about.labels.
headersOut security_result.about.labels Il valore viene estratto dal campo headersOut del log non elaborato e mappato a security_result.about.labels.
ID principal.process.pid Il valore viene estratto dal campo id del log non elaborato e mappato a principal.process.pid.
messaggio metadata.description Il valore viene estratto dal campo message del log non elaborato e mappato a metadata.description.
metodo network.http.method Il valore viene estratto dal campo method del log non elaborato e mappato a network.http.method.
ModuleVersion metadata.ingestion_labels Il valore viene estratto dal campo ModuleVersion del log non elaborato e mappato a metadata.ingestion_labels.
msgData.actions security_result.action Il valore viene estratto dal campo msgData.actions del log non elaborato e mappato a security_result.action.
msgData.changes target.resource.attribute.labels Il valore viene estratto dal campo msgData.changes del log non elaborato e mappato a target.resource.attribute.labels.
msgData.conditions security_result.description Il valore viene estratto dal campo msgData.conditions del log non elaborato e mappato a security_result.description.
msgData.detailLink network.http.referral_url Il valore viene estratto dal campo msgData.detailLink del log non elaborato e mappato a network.http.referral_url.
msgData.name target.resource.name Il valore viene estratto dal campo msgData.name del log non elaborato e mappato a target.resource.name.
msgData.reason security_result.summary Il valore viene estratto dal campo msgData.reason del log non elaborato e mappato a security_result.summary.
msgData.sites network.http.user_agent Il valore viene estratto dal campo msgData.sites del log non elaborato e mappato a network.http.user_agent.
protocollo network.application_protocol Il valore viene estratto dal campo protocol del log non elaborato e mappato a network.application_protocol.
remoteCountryCode principal.location.country_or_region Il valore viene estratto dal campo remoteCountryCode del log non elaborato e mappato a principal.location.country_or_region.
remoteHostname target.hostname Il valore viene estratto dal campo remoteHostname del log non elaborato e mappato a target.hostname.
remoteIP target.ip Il valore viene estratto dal campo remoteIP del log non elaborato e mappato a target.ip.
responseCode network.http.response_code Il valore viene estratto dal campo responseCode del log non elaborato e mappato a network.http.response_code.
responseSize network.received_bytes Il valore viene estratto dal campo responseSize del log non elaborato e mappato a network.received_bytes.
serverHostname principal.hostname Il valore viene estratto dal campo serverHostname del log non elaborato e mappato a principal.hostname.
serverName principal.asset.network_domain Il valore viene estratto dal campo serverName del log non elaborato e mappato a principal.asset.network_domain.
tags security_result.detection_fields Il valore viene estratto dal campo tags del log non elaborato e mappato a security_result.detection_fields.
timestamp metadata.event_timestamp Il valore viene estratto dal campo timestamp del log non elaborato e mappato a metadata.event_timestamp.
tlsCipher network.tls.cipher Il valore viene estratto dal campo tlsCipher del log non elaborato e mappato a network.tls.cipher.
tlsProtocol network.tls.version Il valore viene estratto dal campo tlsProtocol del log non elaborato e mappato a network.tls.version.
URI target.url Il valore viene estratto dal campo URI del log non elaborato e mappato a target.url.
userAgent network.http.user_agent Il valore viene estratto dal campo userAgent del log non elaborato e mappato a network.http.user_agent.
uri network.http.referral_url Il valore viene estratto dal campo uri del log non elaborato e mappato a network.http.referral_url.
X-ARR-SSL network.tls.client.certificate.issuer Il valore viene estratto dal campo dell'intestazione X-ARR-SSL utilizzando i filtri grok e kv.
metadata.event_type Il tipo di evento viene determinato dal parser in base alla presenza di informazioni su target e principal. Se sono presenti sia il target che il principale, il tipo di evento è NETWORK_HTTP. Se è presente solo l'entità, il tipo di evento è STATUS_UPDATE. In caso contrario, il tipo di evento è GENERIC_EVENT.
metadata.log_type Il valore è codificato in modo permanente su SIGNAL_SCIENCES_WAF.
metadata.product_name Il valore è codificato in modo permanente su Signal Sciences WAF.
metadata.vendor_name Il valore è codificato in modo permanente su Signal Sciences.
principal.asset.hostname Il valore viene estratto dal campo principal.hostname.
target.asset.hostname Il valore viene estratto dal campo target.hostname.
target.asset.ip Il valore viene estratto dal campo target.ip.
target.user.user_display_name Il valore viene estratto dal campo message_data utilizzando un filtro grok.
target.user.userid Il valore viene estratto dal campo message_data utilizzando un filtro grok.

Hai bisogno di ulteriore assistenza? Ricevi risposte dai membri della community e dai professionisti di Google SecOps.