Coletar registros do WAF do Fastly

Compatível com:

Visão geral

Esse analisador extrai campos dos registros JSON do WAF do Fastly, transforma e renomeia esses campos e os mapeia para o UDM. Ele processa vários tipos de dados, converte níveis de gravidade e categoriza eventos com base nas informações disponíveis de IP e nome do host. Ele também lida com possíveis falhas de análise e descarta entradas de registro malformadas.

Antes de começar

Verifique se você atende aos seguintes pré-requisitos:

  • Instância do Google SecOps.
  • Conta da Fastly com acesso para configurar as definições do WAF.

Configurar feeds

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

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

Configure 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, Registros do WAF do Fastly).
  5. Selecione Webhook como o Tipo de origem.
  6. Selecione Fastly WAF como o Tipo de registro.
  7. Clique em Próxima.
  8. Opcional: especifique valores para os seguintes parâmetros de entrada:
    • Delimitador de divisão: o delimitador usado para separar linhas de registro, como \n.
  9. Clique em Próxima.
  10. Revise a configuração do feed na tela Finalizar e clique em Enviar.
  11. Clique em Gerar chave secreta para autenticar o feed.
  12. Copie e armazene a chave secreta. Não é possível ver essa chave secreta novamente. Se necessário, você pode gerar uma nova chave secreta, mas isso torna a anterior obsoleta.
  13. Na guia Detalhes, copie o URL do endpoint do feed no campo Informações do endpoint. É necessário especificar esse URL de endpoint no aplicativo cliente.
  14. Clique em Concluído.

Configurar feeds na Central de conteúdo

Especifique valores para os seguintes campos:

  • Delimitador de divisão: o delimitador usado para separar linhas de registro, como \n.

Opções avançadas

  • Nome do feed: um valor pré-preenchido 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 ingestão: rótulos aplicados a todos os eventos deste feed.

  • Clique em Gerar chave secreta para autenticar o feed.

  • Copie e armazene a chave secreta. Não é possível ver essa chave secreta novamente. Se necessário, você pode gerar uma nova chave secreta, mas isso torna a anterior obsoleta.

  • Na guia Detalhes, copie o URL do endpoint do feed no campo Informações do endpoint. É necessário especificar esse URL de endpoint no aplicativo cliente.

Criar uma chave de API para o feed de webhook

  1. Acesse console doGoogle Cloud > Credenciais.

    Ir para Credenciais

  2. Clique em Criar credenciais e, em seguida, selecione Chave de API.

  3. Restrinja o acesso da chave de API à API Google Security Operations.

Especifique o URL do endpoint

  1. No aplicativo cliente, especifique o URL do endpoint HTTPS fornecido no feed do webhook.
  2. Ative a autenticação especificando a chave de API e a chave secreta como parte do cabeçalho personalizado no seguinte formato:

    X-goog-api-key = API_KEY
    X-Webhook-Access-Key = SECRET
    

    Recomendação: especifique a chave de API como um cabeçalho em vez de no URL.

  3. Se o cliente de webhook não aceitar cabeçalhos personalizados, especifique a chave de API e a chave secreta usando parâmetros de consulta no seguinte formato:

    ENDPOINT_URL?key=API_KEY&secret=SECRET
    

    Substitua:

    • ENDPOINT_URL: o URL do endpoint do feed.
    • API_KEY: a chave de API para autenticar no Google Security Operations.
    • SECRET: a chave secreta gerada para autenticar o feed.

Configurar webhook no Fastly

  1. Faça login no Fastly.
  2. Opcional: selecione um site no menu Sites (se você tiver mais de um).
  3. Selecione Gerenciar > Integrações do site.
  4. Clique em Adicionar integração do site.
  5. Selecione Webhook genérico.
  6. URL do webhook: insira o ENDPOINT_URL do Google SecOps, seguido por API_KEY e SECRET.
  7. Posicionamento do alerta: selecione Toda a atividade ou Atividade específica.
  8. Opcional: se você selecionou Atividade específica, acesse o menu "Atividade" e selecione os tipos de atividade que você quer que o webhook envie.
  9. Clique em Criar integração de site.

Tabela de mapeamento do UDM

Campo de registro Mapeamento do UDM Lógica
anomaly_score security_result.detection_fields[].key: "anomaly"
security_result.detection_fields[].value: anomaly_score
Se waf.score.anomaly for 0 ou estiver vazio e anomaly_score não estiver vazio ou for 0, o valor de anomaly_score será usado para preencher a matriz security_result.detection_fields com uma chave "anomaly" e o valor do campo anomaly_score.
cache_status additional.fields[].key: "cache_status"
additional.fields[].value.string_value: cache_status
O valor cache_status é usado para preencher a matriz additional.fields com uma chave "cache_status" e o valor do campo cache_status.
client_ip principal.ip: client_ip O campo client_ip é mapeado para principal.ip.
connection.fastly_is_edge additional.fields[].key: "fastly_is_edge"
additional.fields[].value.bool_value: connection.fastly_is_edge
O valor connection.fastly_is_edge é usado para preencher a matriz additional.fields com uma chave "fastly_is_edge" e o valor do campo connection.fastly_is_edge.
connection.fastly_is_shield additional.fields[].key: "fastly_is_shield"
additional.fields[].value.bool_value: connection.fastly_is_shield
O valor connection.fastly_is_shield é usado para preencher a matriz additional.fields com uma chave "fastly_is_shield" e o valor do campo connection.fastly_is_shield.
connection.request_tls_version network.tls.version: connection.request_tls_version O campo connection.request_tls_version é mapeado para network.tls.version.
fastly.server target.hostname: fastly.server O campo fastly.server é mapeado para target.hostname.
fastly.service_id additional.fields[].key: "service_id"
additional.fields[].value.string_value: fastly.service_id
O valor fastly.service_id é usado para preencher a matriz additional.fields com uma chave "service_id" e o valor do campo fastly.service_id.
geo.city principal.location.city: geo.city O campo geo.city é mapeado para principal.location.city.
geo.country principal.location.country_or_region: geo.country O campo geo.country é mapeado para principal.location.country_or_region.
geo.location principal.location.region_latitude: extraído de geo.location
principal.location.region_longitude: extraído de geo.location
A latitude e a longitude são extraídas do campo geo.location usando uma expressão regular e mapeadas para principal.location.region_latitude e principal.location.region_longitude, respectivamente.
geo.region principal.location.state: geo.region O campo geo.region é mapeado para principal.location.state.
host principal.hostname: host O campo host é mapeado para principal.hostname.
request_headers.accept_charset additional.fields[].key: "accept_charset"
additional.fields[].value.string_value: request_headers.accept_charset
O valor request_headers.accept_charset é usado para preencher a matriz additional.fields com uma chave "accept_charset" e o valor do campo request_headers.accept_charset.
request_headers.accept_language additional.fields[].key: "accept_language"
additional.fields[].value.string_value: request_headers.accept_language
O valor request_headers.accept_language é usado para preencher a matriz additional.fields com uma chave "accept_language" e o valor do campo request_headers.accept_language.
request_headers.referer network.http.referral_url: request_headers.referer O campo request_headers.referer é mapeado para network.http.referral_url.
request_headers.user_agent network.http.user_agent: request_headers.user_agent O campo request_headers.user_agent é mapeado para network.http.user_agent.
request_id metadata.product_log_id: request_id O campo request_id é mapeado para metadata.product_log_id.
request_method network.http.method: request_method O campo request_method é mapeado para network.http.method.
response_headers.cache_control additional.fields[].key: "cache_control"
additional.fields[].value.string_value: response_headers.cache_control
O valor response_headers.cache_control é usado para preencher a matriz additional.fields com uma chave "cache_control" e o valor do campo response_headers.cache_control.
response_headers.content_type additional.fields[].key: "content_type"
additional.fields[].value.string_value: response_headers.content_type
O valor response_headers.content_type é usado para preencher a matriz additional.fields com uma chave "content_type" e o valor do campo response_headers.content_type.
response_state additional.fields[].key: "response_state"
additional.fields[].value.string_value: response_state
O valor response_state é usado para preencher a matriz additional.fields com uma chave "response_state" e o valor do campo response_state.
response_status network.http.response_code: response_status O campo response_status é mapeado para network.http.response_code se o campo status estiver vazio.
rule_id security_result.rule_id: rule_id Se waf.rule_id estiver vazio, o valor de rule_id será usado para preencher security_result.rule_id.
severity waf.severity: severity O valor do campo severity é copiado para waf.severity.
size_bytes.request_header network.sent_bytes: size_bytes.request_header O campo size_bytes.request_header é mapeado para network.sent_bytes.
size_bytes.response_header network.received_bytes: size_bytes.response_header O campo size_bytes.response_header é mapeado para network.received_bytes.
status network.http.response_code: status O campo status é mapeado para network.http.response_code.
timestamp metadata.event_timestamp: timestamp O campo timestamp é analisado e mapeado para metadata.event_timestamp.
url target.url: url O campo url é mapeado para target.url.
waf.blocked security_result.action: derivado Se waf.blocked for "false", security_result.action será definido como "ALLOW". Se waf.blocked for verdadeiro, security_result.action será definido como "BLOCK".
waf.executed security_result.detection_fields[].key: "executed"
security_result.detection_fields[].value: waf.executed
O valor waf.executed é usado para preencher a matriz security_result.detection_fields com uma chave "executed" e o valor do campo waf.executed.
waf.failures security_result.detection_fields[].key: "failures"
security_result.detection_fields[].value: waf.failures
O valor waf.failures é usado para preencher a matriz security_result.detection_fields com uma chave "failures" e o valor do campo waf.failures.
waf.logged security_result.detection_fields[].key: "logged"
security_result.detection_fields[].value: waf.logged
O valor waf.logged é usado para preencher a matriz security_result.detection_fields com uma chave "logged" e o valor do campo waf.logged.
waf.message metadata.description: waf.message Se waf.message não estiver vazio, ele será mapeado para metadata.description.
waf.rule_id security_result.rule_id: waf.rule_id Se waf.rule_id não estiver vazio, ele será mapeado para security_result.rule_id.
waf.score.anomaly security_result.detection_fields[].key: "anomaly"
security_result.detection_fields[].value: waf.score.anomaly
Se waf.score.anomaly não for 0 nem estiver vazio, o valor será usado para preencher a matriz security_result.detection_fields com uma chave "anomaly" e o valor do campo waf.score.anomaly.
waf.score.http_violation security_result.detection_fields[].key: "http_violation"
security_result.detection_fields[].value: waf.score.http_violation
Se waf.score.http_violation não for 0 nem estiver vazio, o valor será usado para preencher a matriz security_result.detection_fields.
waf.score.lfi security_result.detection_fields[].key: "lfi"
security_result.detection_fields[].value: waf.score.lfi
Lógica semelhante a waf.score.http_violation.
waf.score.php_injection security_result.detection_fields[].key: "php_injection"
security_result.detection_fields[].value: waf.score.php_injection
Lógica semelhante a waf.score.http_violation.
waf.score.rce security_result.detection_fields[].key: "rce"
security_result.detection_fields[].value: waf.score.rce
Lógica semelhante a waf.score.http_violation.
waf.score.rfi security_result.detection_fields[].key: "rfi"
security_result.detection_fields[].value: waf.score.rfi
Lógica semelhante a waf.score.http_violation.
waf.score.session_fixation security_result.detection_fields[].key: "session_fixation"
security_result.detection_fields[].value: waf.score.session_fixation
Lógica semelhante a waf.score.http_violation.
waf.score.sql_injection security_result.detection_fields[].key: "sql_injection"
security_result.detection_fields[].value: waf.score.sql_injection
Lógica semelhante a waf.score.http_violation.
waf.score.xss security_result.detection_fields[].key: "xss"
security_result.detection_fields[].value: waf.score.xss
Lógica semelhante a waf.score.http_violation.
waf.severity security_result.severity: derived
security_result.severity_details: waf.severity
Se waf.severity não estiver vazio, ele vai determinar o valor de security_result.severity com base em intervalos (<=3: HIGH, >3 e <=6: MEDIUM, >6 e <=8: LOW, else: UNKNOWN_SEVERITY). O valor original waf.severity também é mapeado para security_result.severity_details.
waf_message metadata.description: waf_message Se waf.message estiver vazio e waf_message não estiver, ele será mapeado para metadata.description. Se client_ip ou host e fastly.server não estiverem vazios, metadata.event_type será definido como "NETWORK_HTTP". Caso contrário, se client_ip ou host não estiverem vazios, metadata.event_type será definido como "STATUS_UPDATE". Caso contrário, será definido como "GENERIC_EVENT". Valor codificado. Valor codificado. Valor codificado.

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