Recolha registos do WAF da Signal Sciences

Compatível com:

Este documento explica como carregar registos do WAF da Signal Sciences para o Google Security Operations através do Google Cloud armazenamento. O analisador transforma os registos da Signal Sciences do respetivo formato JSON no modelo de dados unificado (UDM) do Chronicle. Processa duas estruturas de mensagens principais: as mensagens "RPC.PreRequest/PostRequest" são analisadas através de padrões Grok, enquanto outras mensagens são processadas como objetos JSON, extraindo campos relevantes e mapeando-os para o esquema UDM.

Antes de começar

Certifique-se de que tem os seguintes pré-requisitos:

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

Crie um Google Cloud contentor de armazenamento

  1. Inicie sessão na Google Cloud consola.
  2. Aceda à página Contentores do Cloud Storage.

    Aceda aos contentores

  3. Clique em Criar.

  4. Na página Criar um depósito, introduza as informações do depósito. Após cada um dos passos seguintes, clique em Continuar para avançar para o passo seguinte:

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

      • Introduza um nome exclusivo que cumpra os requisitos do nome do contentor (por exemplo, vpcflow-logs).
      • Para ativar o espaço de nomes hierárquico, clique na seta de expansão para expandir a secção Otimizar para cargas de trabalho orientadas para ficheiros e com grande volume de dados e, de seguida, selecione Ativar espaço de nomes hierárquico neste contentor.
      • Para adicionar uma etiqueta de grupo, clique na seta de expansão para expandir a secção Etiquetas.
      • Clique em Adicionar etiqueta e especifique uma chave e um valor para a etiqueta.
    2. Na secção Escolha onde quer armazenar os seus dados, faça o seguinte:

      • Selecione um Tipo de localização.
      • Use o menu do tipo de localização para selecionar uma Localização onde os dados de objetos no seu contentor vão ser armazenados permanentemente.
      • Para configurar a replicação entre contentores, expanda a secção Configurar replicação entre contentores.
    3. Na secção Escolha uma classe de armazenamento para os seus dados, selecione uma classe de armazenamento predefinida para o contentor ou selecione Autoclass para a gestão automática da classe de armazenamento dos dados do seu contentor.

    4. Na secçã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 controlo de acesso para os objetos do seu contentor.

    5. Na secção Escolha como proteger os dados de objetos, faça o seguinte:

      • Selecione qualquer uma das opções em Proteção de dados que quer definir para o seu contentor.
      • Para escolher como os dados de objetos vão ser encriptados, clique na seta de expansão com a etiqueta Encriptação de dados e selecione um Método de encriptação de dados.
  5. Clique em Criar.

Configure uma chave da API WAF da Signal Sciences

  1. Inicie sessão na IU Web da Signal Sciences WAF.
  2. Aceda a O meu perfil > Tokens de acesso à API.
  3. Clique em Adicionar token de acesso à API.
  4. Indique um nome descritivo e exclusivo (por exemplo, Google SecOps).
  5. Clique em Criar token de acesso à API.
  6. Copie e guarde o token num local seguro.
  7. Clique em Compreendo para concluir a criação do token.

Implemente um script num anfitrião Linux para extrair registos do Signal Sciences e armazená-los no Google Cloud

  1. Inicie sessão no anfitrião Linux através do SSH.
  2. Instale a biblioteca Python para armazenar o JSON do WAF do Signal Sciences num contentor do Cloud Storage:

    pip install google-cloud-storage
    
  3. Defina esta variável de ambiente para chamar o ficheiro 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, uma vez que estas informações não podem ser codificadas:

    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 seguinte guião:

    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)
    

    Configure feeds

Para configurar um feed, siga estes passos:

  1. Aceda a Definições do SIEM > Feeds.
  2. Clique em Adicionar novo feed.
  3. Na página seguinte, clique em Configurar um único feed.
  4. No campo Nome do feed, introduza 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 registo.
  7. Clique em Obter conta de serviço como a conta de serviço do Chronicle.
  8. Clicar em Seguinte.
  9. Especifique valores para os seguintes parâmetros de entrada:

    • URI do contentor de armazenamento: Google Cloud URL do contentor de armazenamento no formato gs://my-bucket/<value>.
    • O URI é um: selecione Diretório que inclui subdiretórios.
    • Opções de eliminação de origens: selecione a opção de eliminação de acordo com a sua preferência.

  10. Clicar em Seguinte.

  11. Reveja a nova configuração do feed no ecrã Finalizar e, de seguida, clique em Enviar.

Tabela de mapeamento do UDM

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

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