Recopila registros del WAF de Fastly
Descripción general
Este analizador extrae campos de los registros JSON del WAF de Fastly, los transforma y cambia de nombre, y los asigna al UDM. Maneja varios tipos de datos, convierte los niveles de gravedad y categoriza los eventos según la información disponible de la dirección IP y el nombre de host. También controla posibles errores de análisis y descarta las entradas de registro con formato incorrecto.
Antes de comenzar
Asegúrate de cumplir con los siguientes requisitos previos:
- Instancia de Google SecOps.
- Cuenta de Fastly con acceso para configurar los parámetros del WAF
Configura feeds
Existen dos puntos de entrada diferentes para configurar feeds en la plataforma de Google SecOps:
- Configuración de SIEM > Feeds
- Centro de contenido > Paquetes de contenido
Configura feeds en Configuración del SIEM > Feeds
Para configurar un feed, sigue estos pasos:
- Ve a Configuración del SIEM > Feeds.
- Haz clic en Agregar feed nuevo.
- En la siguiente página, haz clic en Configurar un solo feed.
- En el campo Nombre del feed, ingresa un nombre para el feed (por ejemplo, Registros del WAF de Fastly).
- Selecciona Webhook como el Tipo de origen.
- Selecciona Fastly WAF como el Tipo de registro.
- Haz clic en Siguiente.
- Opcional: Especifica valores para los siguientes parámetros de entrada:
- Delimitador de división: Es el delimitador que se usa para separar las líneas de registro, como
\n
.
- Delimitador de división: Es el delimitador que se usa para separar las líneas de registro, como
- Haz clic en Siguiente.
- Revisa la configuración del feed en la pantalla Finalizar y, luego, haz clic en Enviar.
- Haz clic en Generar clave secreta para generar una clave secreta que autentique este feed.
- Copia y almacena la clave secreta. No podrás volver a ver esta clave secreta. Si es necesario, puedes regenerar una clave secreta nueva, pero esta acción hace que la clave secreta anterior quede obsoleta.
- En la pestaña Detalles, copia la URL del extremo del feed del campo Información del extremo. Debes especificar esta URL de extremo en tu aplicación cliente.
- Haz clic en Listo.
Configura feeds desde el Centro de contenido
Especifica valores para los siguientes campos:
- Delimitador de división: Es el delimitador que se usa para separar las líneas de registro, como
\n
.
Opciones avanzadas
- Nombre del feed: Es un valor completado previamente que identifica el feed.
- Tipo de fuente: Es el método que se usa para recopilar registros en Google SecOps.
- Espacio de nombres del activo: Es el espacio de nombres asociado con el feed.
Etiquetas de transferencia: Son las etiquetas que se aplican a todos los eventos de este feed.
Haz clic en Generar clave secreta para generar una clave secreta que autentique este feed.
Copia y almacena la clave secreta. No podrás volver a ver esta clave secreta. Si es necesario, puedes regenerar una clave secreta nueva, pero esta acción hace que la clave secreta anterior quede obsoleta.
En la pestaña Detalles, copia la URL del extremo del feed del campo Información del extremo. Debes especificar esta URL de extremo en tu aplicación cliente.
Crea una clave de API para el feed del webhook
Ve a Google Cloud consola > Credenciales.
Haz clic en Crear credenciales y selecciona Clave de API.
Restringe el acceso a la clave de API a la API de Google Security Operations.
Especifica la URL del extremo
- En tu aplicación cliente, especifica la URL del extremo HTTPS que se proporciona en el feed de webhook.
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 un encabezado en lugar de hacerlo en la URL.
Si tu cliente de webhook no admite encabezados personalizados, puedes especificar la clave de API y la clave secreta con parámetros de búsqueda en el siguiente formato:
ENDPOINT_URL?key=API_KEY&secret=SECRET
Reemplaza lo siguiente:
ENDPOINT_URL
: Es la URL del extremo del feed.API_KEY
: Es la clave de API para autenticarse en Google Security Operations.SECRET
: Es la clave secreta que generaste para autenticar el feed.
Configura el webhook en Fastly
- Accede a Fastly.
- Opcional: Selecciona un sitio en el menú Sitios (si tienes más de un sitio).
- Selecciona Administrar > Integraciones del sitio.
- Haz clic en Agregar integración del sitio.
- Selecciona Generic Webhook.
- URL de webhook: Ingresa ENDPOINT_URL de Google SecOps, seguido de API_KEY y SECRET.
- Alert Placement: Selecciona All activity o Specific activity.
- Opcional: Si seleccionaste Actividad específica, ve al menú Actividad y selecciona los tipos de actividad que quieres que envíe el webhook.
- Haz clic en Crear integración del 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 es 0, el valor de anomaly_score se usa para completar el array security_result.detection_fields con una clave de "anomalía" 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 propagar el array additional.fields con una clave de "cache_status" y el valor del campo cache_status . |
client_ip |
principal.ip : client_ip |
El campo client_ip se asigna a principal.ip . |
connection.fastly_is_edge |
additional.fields[].key : "fastly_is_edge"additional.fields[].value.bool_value : connection.fastly_is_edge |
El valor de connection.fastly_is_edge se usa para completar el array additional.fields con una 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 completar el array additional.fields con una 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 se asigna a network.tls.version . |
fastly.server |
target.hostname : fastly.server |
El campo fastly.server se asigna a target.hostname . |
fastly.service_id |
additional.fields[].key : "service_id"additional.fields[].value.string_value : fastly.service_id |
El valor de fastly.service_id se usa para propagar el array additional.fields con una clave de "service_id" y el valor del campo fastly.service_id . |
geo.city |
principal.location.city : geo.city |
El campo geo.city se asigna a principal.location.city . |
geo.country |
principal.location.country_or_region : geo.country |
El campo geo.country se asigna a principal.location.country_or_region . |
geo.location |
principal.location.region_latitude : Se extrajo de geo.location principal.location.region_longitude : Se extrajo de geo.location |
La latitud y la longitud se extraen del campo geo.location con 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 se asigna a principal.location.state . |
host |
principal.hostname : host |
El campo host se asigna a principal.hostname . |
request_headers.accept_charset |
additional.fields[].key : "accept_charset"additional.fields[].value.string_value : request_headers.accept_charset |
El valor de request_headers.accept_charset se usa para completar el array additional.fields con una clave de "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 completar el array additional.fields con una clave de "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 se asigna a network.http.referral_url . |
request_headers.user_agent |
network.http.user_agent : request_headers.user_agent |
El campo request_headers.user_agent se asigna a network.http.user_agent . |
request_id |
metadata.product_log_id : request_id |
El campo request_id se asigna a metadata.product_log_id . |
request_method |
network.http.method : request_method |
El campo request_method se asigna 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 propagar el array additional.fields con una clave de "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 completar el array additional.fields con una clave de "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 completar el array additional.fields con una 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 completar 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 se asigna a network.sent_bytes . |
size_bytes.response_header |
network.received_bytes : size_bytes.response_header |
El campo size_bytes.response_header se asigna a network.received_bytes . |
status |
network.http.response_code : status |
El campo status se asigna 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 se asigna a target.url . |
waf.blocked |
security_result.action : Derivado |
Si waf.blocked es falso, security_result.action se establece en "ALLOW". Si waf.blocked es verdadero, security_result.action se establece en "BLOCK". |
waf.executed |
security_result.detection_fields[].key : "executed"security_result.detection_fields[].value : waf.executed |
El valor de waf.executed se usa para propagar el array security_result.detection_fields con una clave de "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 propagar el array security_result.detection_fields con una clave de "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 de waf.logged se usa para completar el array security_result.detection_fields con una 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 propagar el array security_result.detection_fields con una clave de "anomalía" 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 completar el array 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 : derivedsecurity_result.severity_details : waf.severity |
Si waf.severity no está vacío, determina el valor de security_result.severity según los rangos (<=3: ALTA, >3 y <=6: MEDIA, >6 y <=8: BAJA, de lo contrario: UNKNOWN_SEVERITY). El valor original de 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 está vacío, se asigna a metadata.description . Si client_ip o host y fastly.server no están vacíos, metadata.event_type se establece en "NETWORK_HTTP". De lo contrario, si client_ip o host no están vacíos, metadata.event_type se establece en "STATUS_UPDATE". De lo contrario, se establece como "GENERIC_EVENT". Valor codificado. Valor codificado. Valor codificado. |
¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.