Recolha registos do WAF da Fastly
Vista geral
Este analisador extrai campos dos registos JSON do Fastly WAF, transforma-os, muda-lhes o nome e mapeia-os para o UDM. Processa vários tipos de dados, converte níveis de gravidade e categoriza eventos com base nas informações de IP e nome de anfitrião disponíveis. Também processa potenciais falhas de análise e elimina entradas de registo com formato incorreto.
Antes de começar
Certifique-se de que tem os seguintes pré-requisitos:
- Instância do Google SecOps.
- Conta do Fastly com acesso para configurar as definições da WAF.
Configure feeds
Para configurar um feed, siga estes passos:
- Aceda a Definições do SIEM > Feeds.
- Clique em Adicionar novo feed.
- Na página seguinte, clique em Configurar um único feed.
- No campo Nome do feed, introduza um nome para o feed (por exemplo, Registos da WAF da Fastly).
- Selecione Webhook como o Tipo de origem.
- Selecione Fastly WAF como o Tipo de registo.
- Clicar em Seguinte.
- Opcional: especifique valores para os seguintes parâmetros de entrada:
- Delimitador de divisão: o delimitador usado para separar linhas de registo, como
\n.
- Delimitador de divisão: o delimitador usado para separar linhas de registo, como
- Clicar em Seguinte.
- Reveja a configuração do feed no ecrã Finalizar e, de seguida, clique em Enviar.
- Clique em Gerar chave secreta para gerar uma chave secreta para autenticar este feed.
- Copie e armazene a chave secreta. Não pode ver esta chave secreta novamente. Se necessário, pode regenerar uma nova chave secreta, mas esta ação torna a chave secreta anterior obsoleta.
- No separador Detalhes, copie o URL do ponto final do feed do campo Informações do ponto final. Tem de especificar este URL do ponto final na sua aplicação cliente.
- Clique em Concluído.
Crie uma chave da API para o feed de webhook
Aceda à Google Cloud consola > Credenciais.
Clique em Criar credenciais e, de seguida, selecione Chave de API.
Restrinja o acesso da chave de API à API Google Security Operations.
Especifique o URL do ponto final
- Na aplicação cliente, especifique o URL do ponto final HTTPS fornecido no feed do webhook.
Ative a autenticação especificando a chave da API e a chave secreta como parte do cabeçalho personalizado no seguinte formato:
X-goog-api-key = API_KEY X-Webhook-Access-Key = SECRETRecomendação: especifique a chave da API como um cabeçalho em vez de a especificar no URL.
Se o seu cliente de webhook não suportar cabeçalhos personalizados, pode especificar a chave da API e a chave secreta através de parâmetros de consulta no seguinte formato:
ENDPOINT_URL?key=API_KEY&secret=SECRETSubstitua o seguinte:
ENDPOINT_URL: o URL do ponto final do feed.API_KEY: a chave da API para autenticar no Google Security Operations.SECRET: a chave secreta que gerou para autenticar o feed.
Configure o webhook no Fastly
- Inicie sessão no Fastly.
- Opcional: selecione um site no menu Sites (se tiver mais do que um site).
- Selecione Gerir > Integrações do site.
- Clique em Adicionar integração do site.
- Selecione Webhook genérico.
- URL do webhook: introduza ENDPOINT_URL do Google SecOps, seguido de API_KEY e SECRET.
- Posicionamento de alertas: selecione Toda a atividade ou Atividade específica.
- Opcional: se selecionou Atividade específica, aceda ao menu Atividade e selecione os tipos de atividade que quer que o webhook envie.
- Clique em Criar integração do site.
Tabela de mapeamento da UDM
| Campo de registo | Mapeamento de 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 é usado para preencher a matriz security_result.detection_fields com uma chave de "anomalia" 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 de "cache_status" e o valor do campo cache_status. |
client_ip |
principal.ip: client_ip |
O campo client_ip está 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 de "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 de "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 está mapeado para network.tls.version. |
fastly.server |
target.hostname: fastly.server |
O campo fastly.server está 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 de "service_id" e o valor do campo fastly.service_id. |
geo.city |
principal.location.city: geo.city |
O campo geo.city está mapeado para principal.location.city. |
geo.country |
principal.location.country_or_region: geo.country |
O campo geo.country está mapeado para principal.location.country_or_region. |
geo.location |
principal.location.region_latitude: extraído de geo.locationprincipal.location.region_longitude: extraído de geo.location |
A latitude e a longitude são extraídas do campo geo.location através de uma expressão regular e mapeadas para principal.location.region_latitude e principal.location.region_longitude, respetivamente. |
geo.region |
principal.location.state: geo.region |
O campo geo.region está mapeado para principal.location.state. |
host |
principal.hostname: host |
O campo host está 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 de "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 de "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 está mapeado para network.http.referral_url. |
request_headers.user_agent |
network.http.user_agent: request_headers.user_agent |
O campo request_headers.user_agent está mapeado para network.http.user_agent. |
request_id |
metadata.product_log_id: request_id |
O campo request_id está mapeado para metadata.product_log_id. |
request_method |
network.http.method: request_method |
O campo request_method está 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 de "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 de "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 de "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 é 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 está mapeado para network.sent_bytes. |
size_bytes.response_header |
network.received_bytes: size_bytes.response_header |
O campo size_bytes.response_header está mapeado para network.received_bytes. |
status |
network.http.response_code: status |
O campo status está 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 está mapeado para target.url. |
waf.blocked |
security_result.action: derivada |
Se waf.blocked for falso, security_result.action é definido como "ALLOW". Se waf.blocked for verdadeiro, security_result.action é 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 de "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 de waf.failures é usado para preencher a matriz security_result.detection_fields com uma chave de "falhas" 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 de "logged" e o valor do campo waf.logged. |
waf.message |
metadata.description: waf.message |
Se waf.message não estiver vazio, é mapeado para metadata.description. |
waf.rule_id |
security_result.rule_id: waf.rule_id |
Se waf.rule_id não estiver vazio, é 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 é usado para preencher a matriz security_result.detection_fields com uma chave de "anomalia" 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 é 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 à de 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 à de waf.score.http_violation. |
waf.score.rce |
security_result.detection_fields[].key: "rce"security_result.detection_fields[].value: waf.score.rce |
Lógica semelhante à de waf.score.http_violation. |
waf.score.rfi |
security_result.detection_fields[].key: "rfi"security_result.detection_fields[].value: waf.score.rfi |
Lógica semelhante à de 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 à de 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 à de waf.score.http_violation. |
waf.score.xss |
security_result.detection_fields[].key: "xss"security_result.detection_fields[].value: waf.score.xss |
Lógica semelhante à de waf.score.http_violation. |
waf.severity |
security_result.severity: derivedsecurity_result.severity_details: waf.severity |
Se waf.severity não estiver vazio, determina o valor de security_result.severity com base nos intervalos (<=3: HIGH, >3 e <=6: MEDIUM, >6 e <=8: LOW, caso contrário: UNKNOWN_SEVERITY). O valor waf.severity original também está mapeado para security_result.severity_details. |
waf_message |
metadata.description: waf_message |
Se waf.message estiver vazio e waf_message não estiver vazio, é mapeado para metadata.description. Se client_ip ou host e fastly.server não estiverem vazios, metadata.event_type é definido como "NETWORK_HTTP". Caso contrário, se client_ip ou host não estiverem vazios, metadata.event_type é definido como "STATUS_UPDATE". Caso contrário, é definido como "GENERIC_EVENT". Valor codificado. Valor codificado. Valor codificado. |
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais da Google SecOps.