Recoger registros de Fastly WAF

Disponible en:

Información general

Este analizador extrae campos de los registros JSON de Fastly WAF, los transforma y les cambia el nombre, y los asigna a UDM. Gestiona varios tipos de datos, convierte los niveles de gravedad y clasifica los eventos en función de la información disponible sobre la IP y el nombre de host. También gestiona posibles errores de análisis y elimina las entradas de registro mal formadas.

Antes de empezar

Asegúrate de que cumples los siguientes requisitos previos:

  • Instancia de Google SecOps.
  • Cuenta de Fastly con acceso para configurar los ajustes de WAF.

Configurar feeds

Para configurar un feed, sigue estos pasos:

  1. Ve a Configuración de SIEM > Feeds.
  2. Haz clic en Añadir feed.
  3. En la página siguiente, haga clic en Configurar un solo feed.
  4. En el campo Nombre del feed, introduce un nombre para el feed (por ejemplo, Registros de WAF de Fastly).
  5. Selecciona Webhook como Tipo de fuente.
  6. Seleccione Fastly WAF como Tipo de registro.
  7. Haz clic en Siguiente.
  8. Opcional: Especifica los valores de los siguientes parámetros de entrada:
    • Delimitador de división: el delimitador que se usa para separar las líneas de registro, como \n.
  9. Haz clic en Siguiente.
  10. Revise la configuración del feed en la pantalla Finalizar y, a continuación, haga clic en Enviar.
  11. Haz clic en Generar clave secreta para generar una clave secreta que autentique este feed.
  12. Copia y guarda la clave secreta. No podrás volver a ver esta clave secreta. Si es necesario, puedes volver a generar una clave secreta, pero esta acción hará que la clave secreta anterior quede obsoleta.
  13. En la pestaña Detalles, copie la URL del endpoint del feed del campo Información del endpoint. Debes especificar esta URL de endpoint en tu aplicación cliente.
  14. Haz clic en Listo.

Crear una clave de API para la feed de webhook

  1. Ve a la consolaGoogle Cloud > Credenciales.

    Ir a Credenciales

  2. Haz clic en Crear credenciales y, a continuación, selecciona Clave de API.

  3. Restringe el acceso de la clave de API a la API Google Security Operations.

Especificar la URL del endpoint

  1. En tu aplicación cliente, especifica la URL del endpoint HTTPS proporcionada en el feed de webhook.
  2. Para habilitar la autenticación, especifica la clave de API y la clave secreta como parte del encabezado personalizado con el siguiente formato:

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

    Recomendación: Especifica la clave de API como encabezado en lugar de hacerlo en la URL.

  3. Si tu cliente de webhook no admite encabezados personalizados, puedes especificar la clave de API y la clave secreta mediante parámetros de consulta con el siguiente formato:

    ENDPOINT_URL?key=API_KEY&secret=SECRET
    

    Haz los cambios siguientes:

    • ENDPOINT_URL: URL del endpoint del feed.
    • API_KEY: la clave de API para autenticarte en Google Security Operations.
    • SECRET: la clave secreta que has generado para autenticar el feed.

Configurar webhook en Fastly

  1. Inicia sesión en Fastly.
  2. Opcional: Seleccione un sitio en el menú Sitios (si tiene más de un sitio).
  3. Selecciona Gestionar > Integraciones de sitios.
  4. Haz clic en Añadir integración de sitio.
  5. Selecciona Webhook genérico.
  6. URL de webhook: introduce ENDPOINT_URL de Google SecOps, seguido de API_KEY y SECRET.
  7. Ubicación de las alertas: selecciona Toda la actividad o Actividad específica.
  8. Opcional: Si has seleccionado Actividad específica, ve al menú Actividad y selecciona los tipos de actividad que quieras que envíe el webhook.
  9. Haga clic en Crear integración de sitio.

Tabla de asignación de UDM

Campo de registro Asignación de UDM Lógica
anomaly_score security_result.detection_fields[].key: "anomaly"
security_result.detection_fields[].value: anomaly_score
Si waf.score.anomaly es 0 o está vacío y anomaly_score no está vacío o no es 0, el valor de anomaly_score se usa para rellenar la matriz security_result.detection_fields con la clave "anomaly" y el valor del campo anomaly_score.
cache_status additional.fields[].key: "cache_status"
additional.fields[].value.string_value: cache_status
El valor cache_status se usa para rellenar la matriz additional.fields con la clave "cache_status" y el valor del campo cache_status.
client_ip principal.ip: client_ip El campo client_ip está asignado a principal.ip.
connection.fastly_is_edge additional.fields[].key: "fastly_is_edge"
additional.fields[].value.bool_value: connection.fastly_is_edge
El valor connection.fastly_is_edge se usa para rellenar el array additional.fields con la clave "fastly_is_edge" y el valor del campo connection.fastly_is_edge.
connection.fastly_is_shield additional.fields[].key: "fastly_is_shield"
additional.fields[].value.bool_value: connection.fastly_is_shield
El valor connection.fastly_is_shield se usa para rellenar la matriz additional.fields con la clave "fastly_is_shield" y el valor del campo connection.fastly_is_shield.
connection.request_tls_version network.tls.version: connection.request_tls_version El campo connection.request_tls_version está asignado a network.tls.version.
fastly.server target.hostname: fastly.server El campo fastly.server está asignado a target.hostname.
fastly.service_id additional.fields[].key: "service_id"
additional.fields[].value.string_value: fastly.service_id
El valor fastly.service_id se usa para rellenar el array additional.fields con la clave "service_id" y el valor del campo fastly.service_id.
geo.city principal.location.city: geo.city El campo geo.city está asignado a principal.location.city.
geo.country principal.location.country_or_region: geo.country El campo geo.country está asignado a 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
La latitud y la longitud se extraen del campo geo.location mediante una expresión regular y se asignan a principal.location.region_latitude y principal.location.region_longitude, respectivamente.
geo.region principal.location.state: geo.region El campo geo.region está asignado a principal.location.state.
host principal.hostname: host El campo host está asignado a principal.hostname.
request_headers.accept_charset additional.fields[].key: "accept_charset"
additional.fields[].value.string_value: request_headers.accept_charset
El valor request_headers.accept_charset se usa para rellenar la matriz additional.fields con la clave "accept_charset" y el valor del campo request_headers.accept_charset.
request_headers.accept_language additional.fields[].key: "accept_language"
additional.fields[].value.string_value: request_headers.accept_language
El valor de request_headers.accept_language se usa para rellenar la matriz additional.fields con la clave "accept_language" y el valor del campo request_headers.accept_language.
request_headers.referer network.http.referral_url: request_headers.referer El campo request_headers.referer está asignado a network.http.referral_url.
request_headers.user_agent network.http.user_agent: request_headers.user_agent El campo request_headers.user_agent está asignado a network.http.user_agent.
request_id metadata.product_log_id: request_id El campo request_id está asignado a metadata.product_log_id.
request_method network.http.method: request_method El campo request_method está asignado a network.http.method.
response_headers.cache_control additional.fields[].key: "cache_control"
additional.fields[].value.string_value: response_headers.cache_control
El valor response_headers.cache_control se usa para rellenar la matriz additional.fields con la clave "cache_control" y el valor del campo response_headers.cache_control.
response_headers.content_type additional.fields[].key: "content_type"
additional.fields[].value.string_value: response_headers.content_type
El valor response_headers.content_type se usa para rellenar la matriz additional.fields con la clave "content_type" y el valor del campo response_headers.content_type.
response_state additional.fields[].key: "response_state"
additional.fields[].value.string_value: response_state
El valor response_state se usa para rellenar la matriz additional.fields con la clave "response_state" y el valor del campo response_state.
response_status network.http.response_code: response_status El campo response_status se asigna a network.http.response_code si el campo status está vacío.
rule_id security_result.rule_id: rule_id Si waf.rule_id está vacío, se usa el valor rule_id para rellenar security_result.rule_id.
severity waf.severity: severity El valor del campo severity se copia en waf.severity.
size_bytes.request_header network.sent_bytes: size_bytes.request_header El campo size_bytes.request_header está asignado a network.sent_bytes.
size_bytes.response_header network.received_bytes: size_bytes.response_header El campo size_bytes.response_header está asignado a network.received_bytes.
status network.http.response_code: status El campo status está asignado a network.http.response_code.
timestamp metadata.event_timestamp: timestamp El campo timestamp se analiza y se asigna a metadata.event_timestamp.
url target.url: url El campo url está asignado a target.url.
waf.blocked security_result.action: derivada Si waf.blocked es false, security_result.action tiene el valor "ALLOW". Si waf.blocked es true, security_result.action se define como "BLOCK".
waf.executed security_result.detection_fields[].key: "executed"
security_result.detection_fields[].value: waf.executed
El valor de waf.executed se usa para rellenar la matriz security_result.detection_fields con la clave "executed" y el valor del campo waf.executed.
waf.failures security_result.detection_fields[].key: "failures"
security_result.detection_fields[].value: waf.failures
El valor waf.failures se usa para rellenar la matriz security_result.detection_fields con la clave "failures" y el valor del campo waf.failures.
waf.logged security_result.detection_fields[].key: "logged"
security_result.detection_fields[].value: waf.logged
El valor waf.logged se usa para rellenar la matriz security_result.detection_fields con la clave "logged" y el valor del campo waf.logged.
waf.message metadata.description: waf.message Si waf.message no está vacío, se asigna a metadata.description.
waf.rule_id security_result.rule_id: waf.rule_id Si waf.rule_id no está vacío, se asigna a security_result.rule_id.
waf.score.anomaly security_result.detection_fields[].key: "anomaly"
security_result.detection_fields[].value: waf.score.anomaly
Si waf.score.anomaly no es 0 ni está vacío, el valor se usa para rellenar la matriz security_result.detection_fields con la clave "anomaly" y el valor del campo waf.score.anomaly.
waf.score.http_violation security_result.detection_fields[].key: "http_violation"
security_result.detection_fields[].value: waf.score.http_violation
Si waf.score.http_violation no es 0 ni está vacío, el valor se usa para rellenar la matriz security_result.detection_fields.
waf.score.lfi security_result.detection_fields[].key: "lfi"
security_result.detection_fields[].value: waf.score.lfi
Lógica similar a la 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 similar a la de waf.score.http_violation.
waf.score.rce security_result.detection_fields[].key: "rce"
security_result.detection_fields[].value: waf.score.rce
Lógica similar a la de waf.score.http_violation.
waf.score.rfi security_result.detection_fields[].key: "rfi"
security_result.detection_fields[].value: waf.score.rfi
Lógica similar a la 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 similar a la 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 similar a la de waf.score.http_violation.
waf.score.xss security_result.detection_fields[].key: "xss"
security_result.detection_fields[].value: waf.score.xss
Lógica similar a la de waf.score.http_violation.
waf.severity security_result.severity: derivado
security_result.severity_details: waf.severity
Si waf.severity no está vacío, determina el valor de security_result.severity en función de los intervalos (<=3: ALTA, >3 y <=6: MEDIA, >6 y <=8: BAJA; en caso contrario, UNKNOWN_SEVERITY). El valor original waf.severity también se asigna a security_result.severity_details.
waf_message metadata.description: waf_message Si waf.message está vacío y waf_message no lo está, se asigna a metadata.description. Si client_ip o host y fastly.server no están vacíos, metadata.event_type se define como "NETWORK_HTTP". De lo contrario, si client_ip o host no están vacíos, metadata.event_type se asigna a "STATUS_UPDATE". De lo contrario, se le asigna el valor "GENERIC_EVENT". Valor codificado. Valor codificado. Valor codificado.

¿Necesitas más ayuda? Recibe respuestas de los miembros de la comunidad y de los profesionales de Google SecOps.