Recopila registros de WAF de Fastly
Descripción general
Este analizador extrae campos de los registros JSON de WAF de Fastly, los transforma, les cambia el nombre y los asigna a la UDM. Controla varios tipos de datos, convierte los niveles de gravedad y clasifica los eventos según la información de IP y nombre de host disponible. También controla las posibles fallas de análisis y descarta las entradas de registro con el formato incorrecto.
Antes de comenzar
- Asegúrate de tener una instancia de Google SecOps.
- Una cuenta de Fastly con acceso para configurar la configuración de WAF
Configura un feed en Google SecOps para transferir los registros de WAF de Fastly
- Ve a Configuración de SIEM > Feeds.
- Haz clic en Agregar nueva.
- En el campo Nombre del feed, ingresa un nombre para el feed (por ejemplo, Registros de 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
. - Espacio de nombres del activo: Es el espacio de nombres del activo.
- Etiquetas de transferencia: Es la etiqueta que se aplica a los eventos de este feed.
- 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 Generate Secret Key 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 volver a generar 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.
Crea una clave de API para el feed de webhook
Ve a consola de Google Cloud > Credenciales.
Haz clic en Crear credenciales y selecciona Clave de API.
Restringe el acceso de 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 en 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 consulta 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 uno).
- Selecciona Administrar > Integraciones de sitios.
- Haz clic en Agregar integración de sitios.
- Selecciona Webhook genérico.
- URL de webhook: Ingresa ENDPOINT_URL de SecOps de Google, seguido de API_KEY y SECRET.
- Ubicación de la alerta: Selecciona Toda la actividad o Actividad específica.
- 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 de sitios.
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 ni es 0, el valor de anomaly_score se usa para propagar el array security_result.detection_fields con una clave de "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 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 connection.fastly_is_edge se usa para propagar el array additional.fields con una clave de "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 propagar el array additional.fields con una clave de "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 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 extrae de geo.location principal.location.region_longitude : Se extrae 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 request_headers.accept_charset se usa para propagar 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 request_headers.accept_language se usa para propagar 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 propagar 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 propagar el array additional.fields con una clave de "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 propagar 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 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 waf.logged se usa para propagar el array security_result.detection_fields con una clave de "registrado" 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 y no está vacío, el valor se usa para propagar el array security_result.detection_fields con una clave de "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 propagar el array security_result.detection_fields . |
waf.score.lfi |
security_result.detection_fields[].key : "lfi"security_result.detection_fields[].value : waf.score.lfi |
Tiene una 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 |
Tiene una 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 |
Tiene una 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 |
Tiene una 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 |
Tiene una 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 |
Tiene una 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 |
Tiene una lógica similar a la de waf.score.http_violation . |
waf.severity |
security_result.severity : derivadosecurity_result.severity_details : waf.severity |
Si waf.severity no está vacío, determina el valor de security_result.severity en función de los rangos (<=3: ALTA, >3 y <=6: MEDIA, >6 y <=8: BAJA, de lo contrario: UNKNOWN_SEVERITY). El valor waf.severity original 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 hard-coded. Valor hard-coded. Valor hard-coded. |
Cambios
2022-06-06
- Sin embargo, el analizador se creó recientemente.