Coletar registros do WAF da Signal Sciences

Compatível com:

Este documento explica como transferir os registros do WAF da Signal Sciences para as Operações de segurança do Google usando o Google Cloud Storage. O analisador transforma os registros da Signal Sciences do formato JSON no modelo de dados unificado (UDM, na sigla em inglês) do Chronicle. Ele processa duas estruturas de mensagens principais: as mensagens "RPC.PreRequest/PostRequest" são analisadas usando padrões Grok, enquanto outras mensagens são processadas como objetos JSON, extraindo campos relevantes e mapeando-os para o esquema da UDM.

Antes de começar

Verifique se você tem os pré-requisitos a seguir:

  • Instância do Google SecOps
  • O VPC Flow está configurado e ativo no seu Google Cloud ambiente
  • Acesso privilegiado ao WAF da Signal Sciences

Crie um bucket do Google Cloud Storage

  1. Faça login no console do Google Cloud .
  2. Acesse a página Buckets do Cloud Storage.

    Acessar buckets

  3. Clique em Criar.

  4. Na página Criar um bucket, insira as informações do seu bucket. Após cada uma das etapas a seguir, clique em Continuar para prosseguir para a próxima:

    1. Na seção Começar, faça o seguinte:

      • Insira um nome exclusivo que atenda aos requisitos de nome de bucket (por exemplo, vpcflow-logs).
      • Para ativar o namespace hierárquico, clique na seta de expansão para abrir a seção Otimizar para cargas de trabalho orientadas a arquivos e com uso intensivo de dados e selecione Ativar namespace hierárquico neste bucket.
      • Para adicionar um rótulo de bucket, clique na seta de expansão para abrir a seção Rótulos.
      • Clique em Adicionar rótulo e especifique uma chave e um valor para o rótulo.
    2. Na seção Escolha onde armazenar seus dados, faça o seguinte:

      • Selecione um tipo de local.
      • Use o menu do tipo de local para selecionar um Local em que os dados de objetos no bucket serão armazenados permanentemente.
      • Para configurar a replicação entre buckets, abra a seção Configurar a replicação entre buckets.
    3. Na seção Escolha uma classe de armazenamento para seus dados, selecione uma classe de armazenamento padrão para o bucket ou selecione Classe automática para gerenciamento automático da classe de armazenamento dos dados do bucket.

    4. Na seção Escolha como controlar o acesso a objetos, selecione não para aplicar a prevenção de acesso público e selecione um modelo de controle de acesso para os objetos do bucket.

    5. Na seção Escolha como proteger os dados do objeto, faça o seguinte:

      • Selecione qualquer uma das opções em Proteção de dados que você quer definir para o bucket.
      • Para escolher como os dados do objeto serão criptografados, clique na seta de expansão identificada como Criptografia de dados e selecione um método de criptografia de dados.
  5. Clique em Criar.

Configurar uma chave de API do WAF da Signal Sciences

  1. Faça login na UI da Web do Signal Sciences WAF.
  2. Acesse Meu perfil > Tokens de acesso da API.
  3. Clique em Adicionar token de acesso à API.
  4. Forneça um nome exclusivo e descritivo (por exemplo, Google SecOps).
  5. Clique em Criar token de acesso à API.
  6. Copie e salve o token em um local seguro.
  7. Clique em Entendi para concluir a criação do token.

Implantar um script em um host Linux para extrair registros do Signal Sciences e armazená-los em Google Cloud

  1. Faça login no host Linux usando SSH.
  2. Instale a biblioteca Python para armazenar o JSON do WAF da Signal Sciences em um bucket do Cloud Storage:

    pip install google-cloud-storage
    
  3. Defina essa variável de ambiente para chamar o arquivo JSON que tem as credenciais de Google Cloud:

    export GOOGLE_APPLICATION_CREDENTIALS="path/to/your/service-account-key.json"
    
  4. Configure as seguintes variáveis de ambiente, porque essas informações não podem ser codificadas em disco:

    export SIGSCI_EMAIL=<Signal_Sciences_account_email>
    export SIGSCI_TOKEN=<Signal_Sciences_API_token>
    export SIGSCI_CORP=<Corporation_name_in_Signal_Sciences>
    
  5. Execute o script a seguir:

    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 = '[email protected]'  # 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)
    

    Configurar feeds

Há dois pontos de entrada diferentes para configurar feeds na plataforma Google SecOps:

  • Configurações do SIEM > Feeds
  • Hub de conteúdo > Pacotes de conteúdo

Configurar feeds em "Configurações do SIEM" > "Feeds"

Para configurar um feed, siga estas etapas:

  1. Acesse Configurações do SIEM > Feeds.
  2. Clique em Adicionar novo feed.
  3. Na próxima página, clique em Configurar um único feed.
  4. No campo Nome do feed, insira um nome para o feed (por exemplo, Signal Sciences WAF Logs).
  5. Selecione Google Cloud Storage como o Tipo de origem.
  6. Selecione Signal Sciences WAF como o Tipo de registro.
  7. Clique em Pegar conta de serviço como a Conta de serviço do Chronicle.
  8. Clique em Próxima.
  9. Especifique valores para os seguintes parâmetros de entrada:

    • URI do bucket do Cloud Storage: Google Cloud URL do bucket do Cloud Storage no formato gs://my-bucket/<value>.
    • URI Is A: selecione Directory which includes subdirectories.
    • Opções de exclusão de origem: selecione a opção de exclusão de acordo com sua preferência.

  10. Clique em Próxima.

  11. Revise a configuração do novo feed na tela Finalizar e clique em Enviar.

Configurar feeds na Central de conteúdo

Especifique valores para os seguintes campos:

  • URI do bucket do Cloud Storage: Google Cloud URL do bucket do Cloud Storage no formato gs://my-bucket/<value>.
  • URI Is A: selecione Directory which includes subdirectories.
  • Opções de exclusão de origem: selecione a opção de exclusão de acordo com sua preferência.

Opções avançadas

  • Nome do feed: um valor preenchido automaticamente que identifica o feed.
  • Tipo de origem: método usado para coletar registros no Google SecOps.
  • Namespace do recurso: namespace associado ao feed.
  • Rótulos de transferência: rótulos aplicados a todos os eventos desse feed.

Tabela de mapeamento da UDM

Campo de registro Mapeamento do UDM Lógica
CLIENT-IP target.ip Extraídos do campo de cabeçalho CLIENT-IP.
CLIENT-IP target.port Extraídos do campo de cabeçalho CLIENT-IP.
Conexão security_result.about.labels O valor é extraído do campo Connection do registro bruto e mapeado para security_result.about.labels.
Content-Length security_result.about.labels O valor é extraído do campo Content-Length do registro bruto e mapeado para security_result.about.labels.
Content-Type security_result.about.labels O valor é extraído do campo Content-Type do registro bruto e mapeado para security_result.about.labels.
created metadata.event_timestamp O valor é extraído do campo created do registro bruto e mapeado para metadata.event_timestamp.
details.headersIn security_result.about.resource.attribute.labels O valor é extraído do campo details.headersIn do registro bruto e mapeado para security_result.about.resource.attribute.labels.
details.headersOut security_result.about.resource.attribute.labels O valor é extraído do campo details.headersOut do registro bruto e mapeado para security_result.about.resource.attribute.labels.
details.id principal.process.pid O valor é extraído do campo details.id do registro bruto e mapeado para principal.process.pid.
details.method network.http.method O valor é extraído do campo details.method do registro bruto e mapeado para network.http.method.
details.protocol network.application_protocol O valor é extraído do campo details.protocol do registro bruto e mapeado para network.application_protocol.
details.remoteCountryCode principal.location.country_or_region O valor é extraído do campo details.remoteCountryCode do registro bruto e mapeado para principal.location.country_or_region.
details.remoteHostname target.hostname O valor é extraído do campo details.remoteHostname do registro bruto e mapeado para target.hostname.
details.remoteIP target.ip O valor é extraído do campo details.remoteIP do registro bruto e mapeado para target.ip.
details.responseCode network.http.response_code O valor é extraído do campo details.responseCode do registro bruto e mapeado para network.http.response_code.
details.responseSize network.received_bytes O valor é extraído do campo details.responseSize do registro bruto e mapeado para network.received_bytes.
details.serverHostname principal.hostname O valor é extraído do campo details.serverHostname do registro bruto e mapeado para principal.hostname.
details.serverName principal.asset.network_domain O valor é extraído do campo details.serverName do registro bruto e mapeado para principal.asset.network_domain.
details.tags security_result.detection_fields O valor é extraído do campo details.tags do registro bruto e mapeado para security_result.detection_fields.
details.tlsCipher network.tls.cipher O valor é extraído do campo details.tlsCipher do registro bruto e mapeado para network.tls.cipher.
details.tlsProtocol network.tls.version O valor é extraído do campo details.tlsProtocol do registro bruto e mapeado para network.tls.version.
details.userAgent network.http.user_agent O valor é extraído do campo details.userAgent do registro bruto e mapeado para network.http.user_agent.
details.uri network.http.referral_url O valor é extraído do campo details.uri do registro bruto e mapeado para network.http.referral_url.
eventType metadata.product_event_type O valor é extraído do campo eventType do registro bruto e mapeado para metadata.product_event_type.
headersIn security_result.about.labels O valor é extraído do campo headersIn do registro bruto e mapeado para security_result.about.labels.
headersOut security_result.about.labels O valor é extraído do campo headersOut do registro bruto e mapeado para security_result.about.labels.
ID principal.process.pid O valor é extraído do campo id do registro bruto e mapeado para principal.process.pid.
mensagem metadata.description O valor é extraído do campo message do registro bruto e mapeado para metadata.description.
método network.http.method O valor é extraído do campo method do registro bruto e mapeado para network.http.method.
ModuleVersion metadata.ingestion_labels O valor é extraído do campo ModuleVersion do registro bruto e mapeado para metadata.ingestion_labels.
msgData.actions security_result.action O valor é extraído do campo msgData.actions do registro bruto e mapeado para security_result.action.
msgData.changes target.resource.attribute.labels O valor é extraído do campo msgData.changes do registro bruto e mapeado para target.resource.attribute.labels.
msgData.conditions security_result.description O valor é extraído do campo msgData.conditions do registro bruto e mapeado para security_result.description.
msgData.detailLink network.http.referral_url O valor é extraído do campo msgData.detailLink do registro bruto e mapeado para network.http.referral_url.
msgData.name target.resource.name O valor é extraído do campo msgData.name do registro bruto e mapeado para target.resource.name.
msgData.reason security_result.summary O valor é extraído do campo msgData.reason do registro bruto e mapeado para security_result.summary.
msgData.sites network.http.user_agent O valor é extraído do campo msgData.sites do registro bruto e mapeado para network.http.user_agent.
protocolo network.application_protocol O valor é extraído do campo protocol do registro bruto e mapeado para network.application_protocol.
remoteCountryCode principal.location.country_or_region O valor é extraído do campo remoteCountryCode do registro bruto e mapeado para principal.location.country_or_region.
remoteHostname target.hostname O valor é extraído do campo remoteHostname do registro bruto e mapeado para target.hostname.
remoteIP target.ip O valor é extraído do campo remoteIP do registro bruto e mapeado para target.ip.
responseCode network.http.response_code O valor é extraído do campo responseCode do registro bruto e mapeado para network.http.response_code.
responseSize network.received_bytes O valor é extraído do campo responseSize do registro bruto e mapeado para network.received_bytes.
serverHostname principal.hostname O valor é extraído do campo serverHostname do registro bruto e mapeado para principal.hostname.
serverName principal.asset.network_domain O valor é extraído do campo serverName do registro bruto e mapeado para principal.asset.network_domain.
tags security_result.detection_fields O valor é extraído do campo tags do registro bruto e mapeado para security_result.detection_fields.
timestamp metadata.event_timestamp O valor é extraído do campo timestamp do registro bruto e mapeado para metadata.event_timestamp.
tlsCipher network.tls.cipher O valor é extraído do campo tlsCipher do registro bruto e mapeado para network.tls.cipher.
tlsProtocol network.tls.version O valor é extraído do campo tlsProtocol do registro bruto e mapeado para network.tls.version.
URI target.url O valor é extraído do campo URI do registro bruto e mapeado para target.url.
userAgent network.http.user_agent O valor é extraído do campo userAgent do registro bruto e mapeado para network.http.user_agent.
uri network.http.referral_url O valor é extraído do campo uri do registro bruto e mapeado para network.http.referral_url.
X-ARR-SSL network.tls.client.certificate.issuer O valor é extraído do campo de cabeçalho X-ARR-SSL usando filtros grok e kv.
metadata.event_type O tipo de evento é determinado pelo analisador com base na presença de informações de destino e principais. Se o alvo e o principal estiverem presentes, o tipo de evento será NETWORK_HTTP. Se apenas o principal estiver presente, o tipo de evento será STATUS_UPDATE. Caso contrário, o tipo de evento é GENERIC_EVENT.
metadata.log_type O valor é fixado em SIGNAL_SCIENCES_WAF.
metadata.product_name O valor é fixado em Signal Sciences WAF.
metadata.vendor_name O valor é fixado em Signal Sciences.
principal.asset.hostname O valor é retirado do campo principal.hostname.
target.asset.hostname O valor é retirado do campo target.hostname.
target.asset.ip O valor é retirado do campo target.ip.
target.user.user_display_name O valor é extraído do campo message_data usando um filtro grok.
target.user.userid O valor é extraído do campo message_data usando um filtro grok.

Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.