Reglas de evento único y múltiple en YARA-L
En este documento, se muestran consultas escritas en YARA-L 2.0. Cada ejemplo demuestra cómo correlacionar eventos dentro del lenguaje de reglas de consulta para identificar amenazas de seguridad, supervisar el comportamiento de las entidades y enriquecer las detecciones con lógica empresarial.
Usa los ejemplos como componentes básicos de YARA-L 2.0, incluida la detección de eventos únicos, la coincidencia de expresiones regulares y el filtrado de rangos de red. Estos ejemplos se organizan en categorías funcionales para ayudarte a progresar desde la lógica básica hasta la correlación avanzada de varios eventos y las detecciones compuestas.
Sintaxis básica y
En los ejemplos de esta sección, se muestra cómo correlacionar de manera eficaz los eventos del UDM y estructurar las consultas en el lenguaje de reglas.
Consulta de evento único
Caso de uso: Detección básica de un tipo de evento específico (por ejemplo, USER_LOGIN) sin necesidad de correlacionar en un período.
Lógica clave: Solo usa las secciones de eventos y condiciones para identificar una sola ocurrencia. Una regla de evento único puede ser:
- Cualquier regla sin una sección
match - Regla con una sección
matchy una secciónconditionque solo verifica la existencia de un evento (por ejemplo,$e,#e > 0,#e >= 1,1 <= #e,0 < #e).
Ejemplo: Búsqueda inicial de acceso del usuario
Regla
En el siguiente ejemplo de regla, se busca un evento de acceso del usuario (USER_LOGIN) y se devuelve el primero que se encuentra en los datos de la empresa almacenados en tu cuenta de Google SecOps:
rule SingleEventRule {
meta:
author = "noone@altostrat.com"
events:
$e.metadata.event_type = "USER_LOGIN"
condition:
$e
}
Buscar
En este ejemplo de búsqueda sin agregar, se generan eventos individuales directamente. Dado que esta consulta no requiere correlación de eventos ni variables de eventos, como $e1, se omiten.
metadata.event_type = "USER_LOGIN"
Panel
Debido a que esta lógica de consulta se enfoca en mostrar eventos específicos no correlacionados en su estado sin procesar, no usa las secciones match ni outcome que se requieren para las visualizaciones del panel.
Ejemplo: Detección de acceso de cinco minutos
Regla
En el siguiente ejemplo, se muestra una regla de evento único que usa la sección match para encontrar a cualquier usuario con al menos un evento de acceso que ocurra en un período de 5 minutos (5m). Verifica la existencia de un evento de acceso del usuario.
rule SingleEventRule {
meta:
author = "alice@example.com"
description = "windowed single event example rule"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user over 5m
condition:
#e > 0
}
Buscar
En este ejemplo de búsqueda estadística, se agrega la actividad en ventanas de saltos de tamaño constante de cinco minutos (5m), con un resultado de una fila por usuario y por ventana. Dado que la búsqueda se centra en los recuentos volumétricos por ventana, se omiten las variables event y las secciones condition, ya que los resultados incluyen inherentemente uno o más eventos. Esta versión usa una ventana de saltos de tamaño constante en lugar de una ventana de salto para garantizar que los resultados se rendericen correctamente en la plataforma.
metadata.event_type = "USER_LOGIN"
principal.user.userid = $user
match:
$user by 5m
Panel
En el siguiente ejemplo, se incorpora una sección outcome para calcular el recuento total de eventos por usuario, lo que ayuda a representar los datos como un valor estadístico a lo largo del tiempo. La consulta usa una ventana de saltos de tamaño constante en lugar de una ventana de salto para asegurarse de que los puntos de datos se asignen a discretos buckets que no se superpongan y proporciona una visualización más clara para las tendencias del panel.
metadata.event_type = "USER_LOGIN"
principal.user.userid = $user
match:
$user by 5m
outcome:
$event_count = count(metadata.id)
Consultas y ajustes
Caso de uso: Detecta ventanas svchost.exeque se inician desde directorios no estándares.
Lógica de la clave: Negación (not) combinada con la coincidencia de expresiones regulares.
Ejemplo: Detección de procesos basada en exclusiones
Regla
La siguiente regla verifica si hay patrones específicos en los datos del evento y crea una detección si los encuentra. Esta regla incluye una variable $e1 para hacer un seguimiento del tipo de evento y el campo metadata.event_type de UDM. La regla verifica si hay coincidencias específicas de expresiones regulares con e1. Cuando se produce el evento $e1, se crea una detección. Se incluye una condición not en la regla para excluir ciertas rutas de acceso no maliciosas. Puedes agregar condiciones not para evitar falsos positivos.
rule suspicious_unusual_location_svchost_execution
{
meta:
author = "Google Cloud Security"
description = "Windows 'svchost' executed from an unusual location"
yara_version = "YL2.0"
rule_version = "1.0"
events:
$e1.metadata.event_type = "PROCESS_LAUNCH"
re.regex($e1.principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
not re.regex($e1.principal.process.command_line, `\\Windows\\System32\\`) nocase
condition:
$e1
}
Buscar
En este ejemplo, se realiza una búsqueda sin agregar para generar eventos individuales. Dado que esta búsqueda no requiere la correlación de eventos en varias instancias, las variables de eventos, como $e1, son innecesarias.
metadata.event_type = "PROCESS_LAUNCH"
re.regex(principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
not re.regex(principal.process.command_line, `\\Windows\\System32\\`) nocase
Panel
Esta sintaxis incorpora secciones de match y outcome para calcular el volumen de eventos a lo largo del tiempo. La función timestamp.get_timestamp() buckets los resultados por día para la visualización de tendencias.
metadata.event_type = "PROCESS_LAUNCH"
re.regex(principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
not re.regex(principal.process.command_line, `\\Windows\\System32\\`) nocase
$date = timestamp.get_timestamp(metadata.event_timestamp.seconds)
match:
$date
outcome:
$event_count = count(metadata.id)
Lógica y rango de la red
Caso de uso: Filtrar la actividad según subredes de IP específicas (CIDR) y hacer coincidir con varios nombres de host posibles.
Lógica clave: Usa la función net.ip_in_range_cidr() para la coincidencia de subredes y el operador OR para verificar varios nombres de host posibles.
net.ip_in_range_cidr(): Esta función verifica si una dirección IP determinada está incluida en una subred de enrutamiento entre dominios sin clases (CIDR) determinada.- Operador lógico
OR: Se usa para combinar varias condiciones. Las condiciones dentro de la sección de eventos se combinan de forma implícita conAND. El operadorORverifica varios nombres de host posibles.
Ejemplo: Coincidencia de un solo evento (rango de IP)
Regla
En el siguiente ejemplo, se muestra una regla de evento único que busca coincidencias entre dos nombres de host específicos y un rango específico de direcciones IP:
rule OrsAndNetworkRange {
meta:
author = "noone@altostrat.com"
events:
// Checks CIDR ranges.
net.ip_in_range_cidr($e.principal.ip, "203.0.113.0/24")
// Detection when the hostname field matches either value using or.
$e.principal.hostname = /pbateman/ or $e.principal.hostname = /sspade/
condition:
$e
}
Buscar
En el siguiente ejemplo de consulta, se identifican los eventos en los que una dirección IP específica se encuentra dentro de un rango CIDR definido y el nombre de host coincide con un patrón de usuario específico:
net.ip_in_range_cidr(principal.ip, "203.0.113.0/24")
principal.hostname = /pbateman/ or principal.hostname = /sspade/
Dado que se trata de una búsqueda y no de una regla de detección, todo el evento se devuelve automáticamente si se cumplen los filtros. Una sección match agrupa los datos por principal.ip y principal.hostname. No se requiere una sección condition, y las variables de evento ($e) se omiten porque no se realiza ninguna correlación de eventos.
Panel
En el siguiente ejemplo de consulta, se agregan los resultados agrupando pares únicos de IP y nombre de host:
net.ip_in_range_cidr(principal.ip, "203.0.113.0/24")
principal.hostname = /pbateman/ or principal.hostname = /sspade/
match:
principal.ip, principal.hostname
Expresiones regulares en las búsquedas
Caso de uso: Busca patrones de cadenas flexibles (por ejemplo, dominios específicos en correos electrónicos) sin tener en cuenta las mayúsculas. Se usa con mayor frecuencia en la Búsqueda y las reglas.
Lógica clave: Usa /regex/ nocase para coincidencias básicas y la función re.regex() para el análisis de campos complejos.
Ejemplo: Filtrado de correos electrónicos
Regla
En el siguiente ejemplo de expresión regular de YARA-L 2.0, se buscan eventos con correos electrónicos recibidos del dominio altostrat.com. Como se agregó nocase a la comparación de la variable $host regex y a la función regex, estas comparaciones no distinguen mayúsculas de minúsculas.
rule RegexRuleExample {
meta:
author = "noone@altostrat.com"
events:
$e.principal.hostname = $host
$host = /.*HoSt.*/ nocase
re.regex($e.network.email.from, `.*altostrat\.com`) nocase
match:
$host over 10m
condition:
#e > 10
}
Buscar
En la interfaz de búsqueda, esta lógica se usa para la búsqueda de amenazas de alta fidelidad y la exploración de datos. En lugar de esperar una alerta automática, los analistas pueden consultar manualmente el UDM para descubrir instancias específicas de nombres de host que coincidan con una convención de nombres junto con dominios de correo electrónico específicos. Este es el método principal para validar la cantidad de estos eventos antes de promoverlos a una regla de detección persistente.
principal.hostname = $host
$host = /.*HoSt.*/ nocase
re.regex(network.email.from, `.*altostrat\.com`) nocase
match:
$host over 10m
Panel
La siguiente lógica identifica patrones de interés agregando la telemetría de hostname y email en buckets de 10 minutos (10m). Cuando se usa en un panel, esta lógica permite que los analistas visualicen la frecuencia de comunicación de recursos específicos (que coinciden con host) con el dominio altostrat.com. Esta vista es esencial para supervisar las tendencias internas de movimiento de datos y para identificar los principales comunicadores en la infraestructura crítica.
principal.hostname = $host
$host = /.*HoSt.*/ nocase
re.regex(network.email.from, `.*altostrat\.com`) nocase
match:
$host over 10m
Ejemplo: Expresión regular del nombre de host
Regla
En el siguiente ejemplo, se identifica cualquier actividad de registro en la que la entidad principal hostname se identifica como un servidor web (webserver) o de desarrollo (devserver). Utiliza una expresión regular que no distingue mayúsculas de minúsculas para garantizar que las variaciones en las convenciones de nomenclatura no generen detecciones perdidas.
rule WebServerOrDevServerActivity {
meta:
author = "Alex"
description = "Detects events where the principal hostname is 'webserver' or 'devserver', ignoring case."
severity = "Informational"
events:
$e.principal.hostname = /webserver|devserver/ nocase
condition:
$e
}
Buscar
En el siguiente ejemplo, principal.hostname = /webserver|devserver/ nocase coincide con nombres de host como "WebServer01", "devserver-test" y "MyWebServers". Este es un caso de uso común para encontrar un evento específico.
// Use /regex/ followed by nocase for a case-insensitive match
principal.hostname = /webserver|devserver/ nocase
Panel
Si bien este ejemplo específico no se visualiza en un panel, esta regla proporciona alertas activas y detección persistente. A diferencia de un panel, que requiere una revisión manual, esto garantiza que cada instancia de actividad en estos servidores se marque y registre automáticamente en el motor de detección para que se pueda buscar de inmediato.
Ejemplo: Busca registros sin procesar
Regla
Mientras que la búsqueda manual se usa para investigaciones puntuales, las reglas de detección proporcionan una supervisión continua de la telemetría las 24 horas, todos los días. Puedes convertir una búsqueda exitosa en una regla de YARA-L para automatizar el proceso de alertas.
Estos son los beneficios clave de las reglas:
- Alertas en tiempo real: Marca automáticamente las coincidencias a medida que ingresan al sistema.
- Persistencia: Elimina la necesidad de volver a ingresar manualmente los términos de búsqueda.
- Acciones de resultado: Se incorporan directamente a la vista de detección para la clasificación de los analistas y la respuesta ante incidentes.
Buscar
Los analistas de seguridad suelen usar regex para buscar en registros sin procesar y sin analizar en Google SecOps. Esta acción permite la coincidencia de patrones flexible para encontrar artefactos específicos, incluso si no están completamente estructurados o indexados. La sintaxis usa barras diagonales:
raw = /host/
Esta consulta devuelve cualquier línea de registro sin procesar en la que aparezca la secuencia de caracteres "host". Entre los ejemplos de contenido de registros sin procesar que coinciden, se puede incluir "hostname": "myhost123".
Panel
No hay una variante de panel dedicada para este tipo de evento específico. Para visualizar estas detecciones a gran escala, puedes hacer lo siguiente:
- Asigna
metadata.event_typea un gráfico de barras o circular en el Creador de paneles. - Haz un seguimiento de la frecuencia de estos eventos durante períodos de 7, 30 o 90 días para identificar anomalías en el comportamiento del usuario.
Campos repetidos con condiciones universales
Caso de uso: Audita los eventos que contienen listas de datos (campos repetidos) para asegurarte de que no haya excepciones de confianza. Por ejemplo, verifica que cada dirección IP asociada con un acceso esté fuera de un rango seguro conocido.
Lógica de clave: Usa el operador all para evaluar cada elemento de un campo repetido en función de una condición específica y demuestra cómo la asignación de un campo repetido a una variable de marcador de posición (por ejemplo, $ip) crea una detección distinta para cada valor único de la lista.
Ejemplo: Validación de IP de acceso sospechoso
Regla
La siguiente regla busca eventos de acceso en los que todas las direcciones IP de origen no coinciden con una dirección IP que se sabe que es segura en un período de cinco minutos (5m).
rule SuspiciousIPLogins {
meta:
author = "alice@example.com"
events:
$e.metadata.event_type = "USER_LOGIN"
// Detects if all source IP addresses in an event do not match "100.97.16.0"
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// it will be detected since "100.97.16.1", "100.97.16.2",
// and "100.97.16.3" all do not match "100.97.16.0".
all $e.principal.ip != "100.97.16.0"
// Assigns placeholder variable $ip to the $e.principal.ip repeated field.
// There will be one detection per source IP address.
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// there will be one detection per address.
$e.principal.ip = $ip
match:
$ip over 5m
condition:
$e
}
Buscar
metadata.event_type = "USER_LOGIN"
// Detects if all source IP addresses in an event do not match "100.97.16.0"
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// it will be detected since "100.97.16.1", "100.97.16.2",
// and "100.97.16.3" all do not match "100.97.16.0".
all principal.ip != "100.97.16.0"
// Assigns placeholder variable $ip to the $e.principal.ip repeated field.
// There will be one detection per source IP address.
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// there will be one detection per address.
principal.ip = $ip
match:
$ip over 5m
Panel
metadata.event_type = "USER_LOGIN"
// Detects if all source IP addresses in an event do not match "100.97.16.0"
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// it will be detected since "100.97.16.1", "100.97.16.2",
// and "100.97.16.3" all do not match "100.97.16.0".
all principal.ip != "100.97.16.0"
// Assigns placeholder variable $ip to the $e.principal.ip repeated field.
// There will be one detection per source IP address.
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// there will be one detection per address.
principal.ip = $ip
match:
$ip over 5m
Ventanas avanzadas
En esta sección, se abordan los patrones de varias etapas y las detecciones activadas por la actividad de otras reglas.
Correlación de múltiples eventos
En esta sección, se muestran ejemplos de cómo hacer un seguimiento de las entidades (usuarios o hosts) en varios eventos o períodos para identificar patrones de comportamiento.
Caso de uso: Detecta viajes imposibles en los que un solo usuario accede a su cuenta desde dos o más ciudades en menos de cinco (5m) minutos.
Lógica clave: Usa la sección match para agrupar por $user y #city > 1 para encontrar valores de ubicación distintos.
Ejemplo: Detección de acceso en varias ciudades
Regla
La siguiente regla busca usuarios que hayan accedido a tu empresa desde dos o más ciudades en menos de 5 minutos (5m), donde $user es la variable match, $udm es la variable de evento y $city y $user son las variables de marcador de posición:
rule DifferentCityLogin {
meta:
events:
$udm.metadata.event_type = "USER_LOGIN"
$udm.principal.user.userid = $user
$udm.principal.location.city = $city
match:
$user over 5m
condition:
$udm and #city > 1
}
En la siguiente explicación, se describe cómo funciona esta regla:
- Agrupa los eventos con el nombre de usuario (
$user) y lo devuelve ($user) cuando se encuentra una coincidencia. - El período es de cinco minutos (
5m); solo se correlacionan los eventos que están a menos de 5 minutos (5m) de distancia. - Busca un grupo de eventos (
$udm) cuyo tipo de evento seaUSER_LOGIN. - Para ese grupo de eventos, la regla llama al ID de usuario como
$usery a la ciudad de acceso como$city. Devuelve una coincidencia si la cantidad distinta de valores de
city(denotada por#city) es mayor que1en el grupo de eventos ($udm) dentro del período de 5 minutos (5m).
Buscar
La siguiente consulta de ejemplo ejecuta una búsqueda estadística equivalente para identificar patrones de viajes imposibles. Agrupa los eventos USER_LOGIN por usuario en un período de cinco minutos (5m) y filtra los resultados para mostrar solo las instancias en las que se detectan varias ciudades distintas para una sola identidad.
events:
metadata.event_type = "USER_LOGIN"
principal.user.userid = $user
principal.location.city = $city
match:
$user over 5m
condition:
#city > 1
Panel
La siguiente consulta de ejemplo proporciona una visualización del panel equivalente para hacer un seguimiento de la posible vulneración de la cuenta. Agrega eventos de USER_LOGIN por usuario en un período de cinco minutos (5m) y filtra las instancias en las que una sola identidad se asocia con más de una ciudad distinta (#city), lo que te permite trazar estas anomalías geográficas de alto riesgo a lo largo del tiempo.
events:
metadata.event_type = "USER_LOGIN"
principal.user.userid = $user
principal.location.city = $city
match:
$user over 5m
condition:
#city > 1
Creación y eliminación rápidas de usuarios
Caso de uso: Identificar las cuentas temporales creadas y, luego, borradas en un período de 4 horas
Lógica clave: Une dos tipos de eventos (USER_CREATION y USER_DELETION) en una variable $user compartida y compara sus marcas de tiempo.
Ejemplo: Creación y eliminación rápidas de usuarios
Regla
En el siguiente ejemplo de regla, se buscan los usuarios que se crearon y, luego, se borraron en un plazo de 4 horas (4h), en el que $create y $delete son las variables del evento, $user es la variable match y no hay variables de marcador de posición:
rule UserCreationThenDeletion {
meta:
events:
$create.target.user.userid = $user
$create.metadata.event_type = "USER_CREATION"
$delete.target.user.userid = $user
$delete.metadata.event_type = "USER_DELETION"
$create.metadata.event_timestamp.seconds <=
$delete.metadata.event_timestamp.seconds
match:
$user over 4h
condition:
$create and $delete
}
Buscar
En el siguiente ejemplo, se muestra una búsqueda de estadísticas de varios eventos que se usa para identificar cambios rápidos en el ciclo de vida de la cuenta. Esta consulta genera una fila por usuario en un período de cuatro horas, correlacionando la creación y la eliminación de identidades.
Como la búsqueda devuelve de forma predeterminada cualquier ventana que contenga los eventos especificados, no se requiere una sección condition.
$create.target.user.userid = $user
$create.metadata.event_type = "USER_CREATION"
$delete.target.user.userid = $user
$delete.metadata.event_type = "USER_DELETION"
$create.metadata.event_timestamp.seconds <=
$delete.metadata.event_timestamp.seconds
match:
$user over 4h
Panel
En el siguiente ejemplo, se muestra una búsqueda en el panel de varios eventos diseñada para generar un gráfico de las tendencias del ciclo de vida de la cuenta a lo largo del tiempo. Con una ventana de saltos de tamaño constante (by 4h), los resultados se asignan a buckets de tiempo discretos que no se superponen, lo que es ideal para la visualización.
Esta variación incluye una sección outcome para calcular el recuento de eventos de creación distintos en cada período. A diferencia de la búsqueda anterior, esta versión no requiere que se devuelvan variables de eventos específicas, ya que el enfoque se centra en los valores estadísticos agregados, en lugar de las líneas de registro individuales.
$create.target.user.userid = $user
$create.metadata.event_type = "USER_CREATION"
$delete.target.user.userid = $user
$delete.metadata.event_type = "USER_DELETION"
$create.metadata.event_timestamp.seconds <=
$delete.metadata.event_timestamp.seconds
match:
$user by 4h
outcome:
$event_count = count_distinct($create.metadata.id)
Ventana deslizante en las consultas
Caso de uso: Detectar un posible problema de seguridad en el que un evento inicial (de firewall_1) no está seguido por un evento posterior esperado (de firewall_2) en el mismo host dentro de un período específico.
Lógica clave:
- Evento dinámico: La regla se centra en los eventos de
firewall_1, designados como$e1. Cada vez que se produce un evento$e1, este actúa como un pivote. - Período: La sección
match($host over 10m after $e1) define un período de 10 minutos que comienza inmediatamente después de cada evento$e1. Esta ventana se desliza con cada evento$e1nuevo. - Correlación: Los eventos se agrupan por nombre de host (
$host). - Condición para la detección (
$e1y$e2): Se activa una detección para un host determinado si se cumple lo siguiente:- Hay un evento de
firewall_1($e1). AND, dentro del período de 10 minutos posterior a ese evento$e1específico, se encuentra el eventoNOdefirewall_2($e2) para el mismo host.
- Hay un evento de
Ejemplo: Detección de eventos secuenciales faltantes
Regla
En el siguiente ejemplo, se identifican las instancias en las que un evento secundario no se produce después de un activador principal. Si se usa la condición !$e2 en un período de 10 minutos, esta regla marca la falta de telemetría, específicamente cuando se ve un registro de firewall en una ubicación, pero no aparece en el siguiente salto esperado, lo que indica una posible brecha de visibilidad o una caída del tráfico.
rule MissingSequentialEvent {
meta:
author = "alice@example.com"
events:
$e1.metadata.product_name = "firewall_1"
$e1.principal.hostname = $host
$e2.metadata.product_name = "firewall_2"
$e2.principal.hostname = $host
match:
// $e1 is the pivot; the 10-minute window starts at the $e1 timestamp
$host over 10m after $e1
condition:
$e1 and !$e2
}
Buscar
En el siguiente ejemplo, se muestra una búsqueda secuencial que se usa para identificar brechas en la telemetría entre dos fuentes. Si se usa $e1 como pivote, la búsqueda busca un evento de firewall principal que no vaya seguido de un evento correspondiente en un segundo firewall en un plazo de 10 minutos. Esta es una forma muy eficaz de buscar manualmente "agujeros negros" en el tráfico de red o fallas de registro durante una investigación.
$e1.metadata.product_name = "firewall_1"
$e1.principal.hostname = $host
$e2.metadata.product_name = "firewall_2"
$e2.principal.hostname = $host
match:
// $e1 is the pivot; the 10-minute window starts at the $e1 timestamp
$host over 10m after $e1
condition:
$e1 and !$e2
Panel
En el siguiente ejemplo, se proporciona un análisis de brechas de visibilidad diseñado para una vista de panel. Si agregas instancias en las que un evento secundario no sigue a uno principal, puedes visualizar la confiabilidad de tu canalización de registros a lo largo del tiempo. Registrar estos eventos "faltantes" ayuda a identificar zonas muertas persistentes en la visibilidad de la red o problemas de configuración en nombres de host específicos.
$e1.metadata.product_name = "firewall_1"
$e1.principal.hostname = $host
$e2.metadata.product_name = "firewall_2"
$e2.principal.hostname = $host
match:
// $e1 is the pivot; the 10-minute window starts at the $e1 timestamp
$host over 10m after $e1
condition:
$e1 and !$e2
Consultas de varios eventos
Caso de uso: Identifica la actividad de alta frecuencia o de fuerza bruta haciendo un seguimiento de una sola entidad (por ejemplo, un usuario o un host) en varias ocurrencias de un evento dentro de un período específico.
Lógica clave: Usa una sección
matchpara agrupar eventos por una variable específica y una secciónconditionpara verificar un recuento de umbral (por ejemplo,#e >= 10) dentro del período definido.
Una regla de varios eventos típica incluye lo siguiente:
- Variables de evento para distinguir entre eventos
- Una sección
matchque especifica el período durante el cual se deben agrupar los eventos. - Una sección
conditionque especifica qué condición debe activar la detección y verificar la existencia de varios eventos.
En la Búsqueda, las consultas de varios eventos se definen por más de un evento en una consulta. En el caso de las reglas, hay dos formas de definir esto:
Varios eventos: (por ejemplo,
event1 = successful login, event2 = failed login).Activadores basados en condiciones: La condición se establece para que se active solo cuando varios eventos cumplen con los criterios (por ejemplo,
event1 > 10). Este tipo de regla también debe incluir una secciónoutcome.
Ejemplo: Detección de acceso de alta frecuencia
Regla
La siguiente regla busca un usuario que se haya conectado al menos 10 veces en menos de 10 minutos:
rule MultiEventRule {
meta:
author = "noone@altostrat.com"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user over 10m
condition:
#e >= 10
}
Buscar
En el siguiente ejemplo, se usa una búsqueda de estadísticas de varios eventos para identificar la actividad de acceso de alta frecuencia. Marca cualquier instancia en la que un solo usuario genere 10 o más eventos de acceso en un período de 10 minutos (10m).
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user by 10m
condition:
#e >= 10
Panel
En el siguiente ejemplo, se usa una búsqueda de varios eventos para supervisar posibles vulneraciones de cuentas. Al correlacionar los intentos de acceso en un período de 10 minutos, identifica los casos en los que un usuario y un host específicos experimentan varios intentos de acceso fallidos seguidos de uno exitoso, lo que te permite visualizar patrones de autenticación de alto riesgo en tiempo real.
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user by 10m
condition:
#e >= 10
Consultas de varios eventos con resultados calculados
Caso de uso: Aplica lógica condicional para establecer un
risk_scoresegún la gravedad del activo o el volumen de la red.Lógica clave: Usa la sección
outcomepara calcular variables y la sección de condiciones para filtrar por esas variables.
Ejemplo: Intento de acceso por fuerza bruta seguido de un acceso exitoso
En el siguiente ejemplo, se usa la sección outcome para contar eventos dentro de una ventana match. Esta consulta genera el mismo resultado que la consulta estándar de varios eventos, pero muestra cómo incorporar variables calculadas en tu lógica de detección.
Regla
rule PossibleBruteForceThenSuccessfulLogin {
meta:
author = "Alex"
description = "Detects multiple failed login attempts followed by a successful login for the same user and host within a 10-minute window."
severity = "High"
tactic = "Credential Access"
events:
// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname
// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname
match:
// This section is key for multi-event rules. It groups events:
// - By the common placeholder variables: $user and $hostname.
// - Within a time window: by 10m.
// The rule will evaluate all events matching $failed or $success that share the same $user and $hostname within any given 10-minute period.
$user, $hostname by 10m
outcome:
// Calculate aggregate values from the events within the match window.
$failed_login_count = count($failed.metadata.id)
$successful_login_count = count($success.metadata.id)
condition:
// The conditions that must be met *within each matched group* ($user, $hostname over 10m).
// - #failed >= 5: There must be 5 or more events matching the $failed criteria.
// - #success >= 1: There must be at least 1 event matching the $success criteria.
#failed >= 5 and #success >= 1
}
Buscar
// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname
// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname
match:
// This section is key for multi-event rules. It groups events:
// - By the common placeholder variables: $user and $hostname.
// - Within a sliding time window: over 10m.
// The rule will evaluate all events matching $failed or $success that share
// the same $user and $hostname within any given 10-minute period.
$user, $hostname over 10m
Panel
// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname
// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname
match:
// This section is key for multi-event rules. It groups events:
// - By the common placeholder variables: $user and $hostname.
// - Within a sliding time window: over 10m.
// The rule will evaluate all events matching $failed or $success that share
// the same $user and $hostname within any given 10-minute period.
$user, $hostname over 10m
Ejemplo: Coincidencia de host con ventana temporal
Regla
La siguiente regla analiza dos eventos para obtener el valor de $hostname. Si el valor de $hostname coincide durante un período de 5 minutos (5m), se aplica una puntuación de gravedad. Cuando se incluye un período en la sección match, la regla realiza la verificación dentro del período especificado.
rule OutcomeRuleMultiEvent {
meta:
author = "Google Cloud Security"
events:
$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname
$severity = $asset_context.graph.entity.asset.vulnerabilities.severity
match:
$hostname over 5m
outcome:
$risk_score =
max(
100
+ if($hostname = "my-hostname", 100, 50)
+ if($severity = "HIGH", 10)
+ if($severity = "MEDIUM", 5)
+ if($severity = "LOW", 1)
)
$asset_id_list =
array(
if($u.principal.asset_id = "",
"Empty asset id",
$u.principal.asset_id
)
)
$asset_id_distinct_list = array_distinct($u.principal.asset_id)
$asset_id_count = count($u.principal.asset_id)
$asset_id_distinct_count = count_distinct($u.principal.asset_id)
condition:
$u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}
Buscar
// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname
// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname
match:
// This section is key for multi-event rules. It groups events:
// - By the common placeholder variables: $user and $hostname.
// - Within a sliding time window: over 10m.
// The rule will evaluate all events matching $failed or $success that share
// the same $user and $hostname within any given 10-minute period.
$user, $hostname over 10m
outcome:
// Calculate aggregate values from the events within the match window.
$failed_login_count = count($failed.metadata.id)
$successful_login_count = count($success.metadata.id)
```
Panel
// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname
// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname
match:
// This section is key for multi-event rules. It groups events:
// - By the common placeholder variables: $user and $hostname.
// - Within a sliding time window: over 10m.
// The rule will evaluate all events matching $failed or $success that share
// the same $user and $hostname within any given 10-minute period.
$user, $hostname over 10m
outcome:
// Calculate aggregate values from the events within the match window.
$failed_login_count = count($failed.metadata.id)
$successful_login_count = count($success.metadata.id)
Análisis adaptados al contexto
Puedes usar reglas de YARA-L para evaluar los datos de eventos del UDM en función de los datos de contexto del indicador de compromiso (IoC). Estos datos de contexto se almacenan como contextos de entidades en Google SecOps.
En los ejemplos de esta sección, se muestra cómo crear estadísticas adaptadas al contexto combinando campos de eventos con feeds de IOC, como la Navegación segura de Google y los feeds personalizados.
Coincidencia de hash de archivos con indicadores de compromiso
Caso de uso: Detecta la ejecución o la presencia de archivos identificados como indicadores de compromiso (IOC) en los feeds de amenazas.
Lógica clave: Une los eventos de procesos o archivos de UDM con las entidades de archivos (hashes) de los feeds de IOC en el gráfico de entidades.
Ejemplo: Lanzamiento de un proceso sospechoso
Regla
La siguiente regla evalúa los datos de proceso de UDM con los datos de contexto de IOC genéricos. Busca un evento de inicio de proceso y une el hash del archivo del evento con un hash del archivo que se encuentra en un gráfico de entidades de IOC.
rule ProcessLaunch {
meta:
events:
$ioc.graph.metadata.vendor_name = "ACME"
$ioc.graph.metadata.product_name = "IOCs"
$ioc.graph.metadata.entity_type = "FILE"
$ioc.graph.entity.file.sha256 = $hash
$process.metadata.event_type = "PROCESS_LAUNCH"
$process.principal.hostname = $hostname
(
not $process.target.process.file.sha256 = "" and
$process.target.process.file.sha256 = $hash
)
match:
$hash over 15m
condition:
$ioc and $process
}
Ejemplo: Listas de amenazas de Navegación segura
Regla
Google SecOps transfiere datos de listas de amenazas relacionadas con hashes de archivos, que se almacenan como entidades. La siguiente regla detecta la ejecución de un archivo que la Navegación segura de Google considera malicioso.
rule safe_browsing_file_execution {
meta:
author = "Google Security Operations"
description = "Example usage of Safe Browsing data, to detect execution of a file that's been deemed malicious"
severity = "LOW"
events:
// find a process launch event, match on hostname
$execution.metadata.event_type = "PROCESS_LAUNCH"
$execution.principal.hostname = $hostname
// join execution event with Safe Browsing graph
$sb.graph.entity.file.sha256 = $execution.target.process.file.sha256
// look for files deemed malicious
$sb.graph.metadata.entity_type = "FILE"
$sb.graph.metadata.threat_intel.severity = "SEVERITY_HIGH"
$sb.graph.metadata.product_name = "Google Safe Browsing"
$sb.graph.metadata.source_type = "GLOBAL_CONTEXT"
match:
$hostname over 1h
outcome:
$risk_score = max(if($sb.graph.metadata.threat_intel.severity = "SEVERITY_HIGH", 90, 0))
condition:
$execution and $sb
}
La dirección IP coincide con los indicadores de compromiso
Caso de uso: Detectar la comunicación de red con direcciones IP maliciosas conocidas almacenadas en feeds de amenazas.
Lógica de claves: Une los eventos de red del UDM con las entidades de direcciones IP de los feeds de IOC en el gráfico de entidades.
Ejemplo: Detección de nodos de salida de Tor
Regla
Identifica el tráfico de red que se origina en nodos de salida de Tor conocidos o que se conecta a ellos. En este ejemplo, se combinan los eventos del UDM con el feed de nodos de salida de Tor del feed de GCTI, que está disponible para todos los clientes.
rule TorExitNodeMatch {
meta:
author = "Google Security Operations"
description = "Detects traffic from known Tor exit nodes."
severity = "MEDIUM"
events:
// Event based on IP
$principal_ip = $e.principal.ip
// Filter Entity Graph to extract feed specific details
$gcti.graph.metadata.entity_type = "IP_ADDRESS"
$gcti.graph.metadata.feed = "Tor Exit Nodes"
$gcti.graph.metadata.product_name = "GCTI Feed"
// Join the IP data
$principal_ip = $gcti.graph.entity.ip
match:
$principal_ip over 30m
outcome:
$threat_feed = array_distinct($gcti.graph.metadata.feed)
condition:
$e and $gcti
}
Ejemplo: Varios intentos de acceso fallidos desde la red Tor
Regla
Detecta varios intentos de acceso fallidos desde una red Tor. En este ejemplo, se correlacionan los eventos login_failure con el feed de nodos de salida de Tor y se aplica un umbral de frecuencia con la sintaxis de recuento (#).
rule TorMultiLoginFailure {
meta:
author = "Google Security Operations"
description = "Detects multiple failed logins from a Tor network."
severity = "HIGH"
events:
$failed_login_event.metadata.product_name = "login"
$failed_login_event.metadata.product_event_type = "login_failure"
$failed_login_event.metadata.vendor_name = "Google Workspace"
$sus_ip = $failed_login_event.principal.ip
$sus_target_account = $failed_login_event.target.user.email_addresses
$sus_target_account != ""
$gcti.graph.metadata.entity_type = "IP_ADDRESS"
$gcti.graph.metadata.feed = "Tor Exit Nodes"
$gcti.graph.metadata.product_name = "GCTI Feed"
// Join the IP data
$sus_ip = $gcti.graph.entity.ip
match:
$sus_ip over 1h
outcome:
$event_count = count_distinct($failed_login_event.metadata.id)
condition:
$failed_login_event and #failed_login_event >= 10 and $gcti
}
Coincidencia de dominios con indicadores de compromiso
Caso de uso: Detectar la actividad de red en dominios marcados como indicadores de compromiso (IOC) o dominios con baja prevalencia
Lógica clave: Une los eventos de red del UDM con las entidades de dominio de los feeds de IOC o los datos de prevalencia en el gráfico de entidades usando el nombre de dominio o el nombre de host.
Ejemplo: Dominios de prevalencia baja
Regla
La siguiente regla genera una alerta de detección comparando un dominio de baja prevalencia con un IOC conocido. Une un evento de consulta de DNS con datos de prevalencia y una entidad de IOC del feed de ET_PRO_IOC.
rule network_prevalence_uncommon_domain_ioc_match {
meta:
author = "Google Security Operations"
description = "Lookup Network DNS queries against Entity Graph for low prevalence domains with a matching IOC entry."
severity = "MEDIUM"
events:
$e.metadata.event_type = "NETWORK_DNS"
$e.network.dns.questions.name = $hostname
//only match FQDNs, such as: exclude chrome dns access tests and other internal hosts
$e.network.dns.questions.name = /(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]/
//prevalence entity graph lookup
$p.graph.metadata.entity_type = "DOMAIN_NAME"
$p.graph.entity.domain.prevalence.rolling_max > 0
$p.graph.entity.domain.prevalence.rolling_max <= 3
$p.graph.entity.domain.name = $hostname
//ioc entity graph lookup
$i.graph.metadata.vendor_name = "ET_PRO_IOC"
$i.graph.metadata.entity_type = "DOMAIN_NAME"
$i.graph.entity.hostname = $hostname
match:
$hostname over 10m
outcome:
$risk_score = max(
//increment risk score based upon rolling_max prevalence
if ( $p.graph.entity.domain.prevalence.rolling_max = 3, 50) +
if ( $p.graph.entity.domain.prevalence.rolling_max = 2, 70) +
if ( $p.graph.entity.domain.prevalence.rolling_max = 1, 90)
)
condition:
$e and $p and $i
}
Coincidencia de URLs con indicadores de compromiso
Caso de uso: Detectar actividad de red que involucre URLs maliciosas almacenadas en feeds de amenazas.
Lógica clave: Une los eventos de red de UDM que contienen datos de URLs con entidades de URLs de feeds de IOC en el gráfico de entidades.
Ejemplo: Coincidencia de URL maliciosa del feed de amenazas
Regla
La siguiente regla detecta eventos de red en los que la URL solicitada coincide con una URL maliciosa conocida de un feed de inteligencia contra amenazas. Correlaciona el target.url del evento con las entidades de URL en el gráfico de entidades.
rule ioc_url_threat_feed_match {
meta:
author = "Google Security Operations"
description = "Matches network events against known malicious URLs from threat intelligence feeds."
severity = "HIGH"
events:
// Filter for network traffic containing URL information
$network_event.metadata.event_type = "NETWORK_HTTP" or $network_event.metadata.event_type = "NETWORK_CONNECTION"
$url = $network_event.target.url
// Entity Graph Join: URL Indicators
$ioc.graph.metadata.entity_type = "URL"
$ioc.graph.metadata.product_name = "GCTI Feed"
$ioc.graph.metadata.feed = "Malicious URLs"
$ioc.graph.entity.url = $url
match:
$url over 5m
outcome:
$risk_score = 85
$threat_feed = array_distinct($ioc.graph.metadata.feed)
$principal_ip = array_distinct($network_event.principal.ip)
$principal_user = array_distinct($network_event.principal.user.userid)
condition:
$network_event and $ioc
}
Coincidencia simultánea de varios feeds
Caso de uso: Correlaciona amenazas avanzadas haciendo coincidir varios atributos (por ejemplo, la dirección IP y el hash del archivo) con feeds de amenazas separados dentro de una sola consulta de eventos.
Lógica clave: Une un solo evento de UDM con varios marcadores de posición del gráfico de entidades, cada uno filtrado para un threat_feed_name específico (por ejemplo, Google Cloud feeds de inteligencia contra amenazas).
Ejemplo: Detección de nodo de salida de Tor y herramienta de acceso remoto
Regla
La siguiente regla marca el tráfico de red que parece estar asociado con la supervisión y administración remotas (RMM) y que se origina en un nodo de salida de Tor o se conecta a él. Se une un evento NETWORK_CONNECTION a un feed de IP (nodos de salida de Tor) y a un feed de hash de archivo (herramientas de acceso remoto).
rule tor_and_remote_access_tool_match {
meta:
author = "Google Security Operations"
description = "Matches network connections involving both a Tor exit node and Remote Access Tool malware hashes."
severity = "CRITICAL"
events:
// Filter for network connection events, often recorded by EDR agents
$e.metadata.event_type = "NETWORK_CONNECTION"
$target_ip = $e.target.ip
$process_hash = $e.principal.process.file.sha256
// IP Feed Join: Tor Exit Nodes
$gcti_ip.graph.metadata.entity_type = "IP_ADDRESS"
$gcti_ip.graph.metadata.product_name = "GCTI Feed"
$gcti_ip.graph.metadata.feed = "Tor Exit Nodes"
$gcti_ip.graph.entity.ip = $target_ip
// Hash Feed Join: Remote Access Tools
$gcti_hash.graph.metadata.entity_type = "FILE"
$gcti_hash.graph.metadata.product_name = "GCTI Feed"
$gcti_hash.graph.metadata.feed = "Remote Access Tools"
$gcti_hash.graph.entity.file.sha256 = $process_hash
match:
$target_ip over 10m
outcome:
$risk_score = 95
$ip_feed = array_distinct($gcti_ip.graph.metadata.feed)
$hash_feed = array_distinct($gcti_hash.graph.metadata.feed)
condition:
$e and $gcti_ip and $gcti_hash
}
Detecciones compuestas
Las detecciones compuestas mejoran la detección de amenazas con reglas compuestas. Estas reglas compuestas usan las detecciones de otras reglas como entrada. Esto permite detectar amenazas complejas que las reglas individuales podrían no detectar. Para obtener más información, consulta Descripción general de las detecciones compuestas.
Filtrado de alto riesgo
Caso de uso: Filtra las detecciones existentes para buscar atributos de alto riesgo, como la actividad que involucra cuentas de administración.
Lógica clave: Opera sobre los resultados o los campos de metadatos dentro de los hallazgos existentes.
Las detecciones compuestas de filtrado de alto riesgo son la forma más simple de detección compuesta, ya que operan en campos dentro de los resultados de detección, como variables de resultado o metadatos de reglas. Ayudan a filtrar las detecciones para las condiciones que pueden indicar un mayor riesgo, como un usuario administrador o un entorno de producción.
Ejemplo: Detección de usuarios administradores
Regla
La siguiente regla compuesta busca cualquier detección existente en la que el actor se identifique como un usuario administrador y aplica una puntuación de riesgo estandarizada.
rule composite_admin_detection {
meta:
rule_name = "Detection with Admin User"
author = "Google Cloud Security"
description = "Composite rule that looks for any detections where the actor is an admin user"
severity = "Medium"
events:
$rule_name = $d.detection.detection.rule_name
$principal_user = $d.detection.detection.variables["principal_users"]
$principal_user = /admin|root/ nocase
match:
$principal_user over 1h
outcome:
$risk_score = 75
$upstream_rules = array_distinct($rule_name)
condition:
$d
}
Buscar
La siguiente búsqueda estadística identifica y agrega la actividad de las cuentas con privilegios elevados. Está diseñada para encontrar todos los nombres de reglas únicos que activaron detecciones que involucran a usuarios "admin" o "root".
En esta búsqueda específica, se quita el período para realizar un solo análisis estadístico en todas las detecciones dentro del período seleccionado. Además, dado que se trata de una búsqueda sin agregar enfocada en los datos de detección existentes, no se requieren la sección de eventos, las variables de eventos ni la sección de condiciones.
$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_users"]
$principal_user = /admin|root/ nocase
match:
$principal_user
outcome:
$upstream_rules = array_distinct($rule_name)
Panel
Esta consulta del panel te permite visualizar qué reglas específicas detectan con mayor frecuencia la actividad relacionada con el administrador. Está diseñado para proporcionar una descripción general de alto nivel de las tendencias de detección en todo tu entorno.
Observa el cambio en la variable match y la agregación outcome en comparación con los ejemplos anteriores. Esta consulta agrupa los resultados por nombre de regla y calcula un recuento de los usuarios administradores detectados para cada uno.
$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_users"]
$principal_user = /admin|root/ nocase
match:
$rule_name
outcome:
$admin_detections = count($principal_user)
Agregación y umbralización
Caso de uso: Identifica a los usuarios o hosts que generan un gran volumen de alertas o acumulan puntuaciones de riesgo significativas con el tiempo.
Lógica de la clave: Usa sum() o count_distinct() para analizar los datos de detección agregados.
Las reglas de detección compuestas de agregación te permiten agrupar los hallazgos de detección según atributos compartidos, como un nombre de host o un nombre de usuario, y analizar los datos agregados. Estos son algunos casos de uso comunes:
- Identificar a los usuarios que generan un gran volumen de alertas de seguridad o riesgo agregado
- Detectar hosts con patrones de actividad inusuales agregando detecciones relacionadas
Ejemplo: Agregación de riesgos
Regla
Esta regla agrega la puntuación de riesgo de un solo usuario durante un período de 48 horas. Identifica a los usuarios cuyo riesgo acumulado en varias detecciones supera un umbral específico.
En esta lógica actualizada, detection.detection.outcomes se reemplaza por variables de campo de mapa, que almacenan las variables match y outcome. Además, se quita la variable de resultado $principal_users porque cada detección contiene exactamente un valor de variable de coincidencia, que ya se captura.
rule composite_risk_aggregation {
meta:
rule_name = "Risk Aggregation Composite"
author = "Google Cloud Security"
description = "Composite detection that aggregates risk of a user over 48 hours"
severity = "High"
events:
$rule_name = $d.detection.detection.rule_name
$principal_user = $d.detection.detection.outcomes["principal_users"]
$risk = $d.detection.detection.risk_score
match:
$principal_user over 48h
outcome:
$risk_score = 90
$cumulative_risk = sum($risk)
$upstream_rules = array_distinct($rule_name)
condition:
$d and $cumulative_risk > 500
}
Buscar
Esta búsqueda estadística agrega datos de detección para calcular el riesgo total de un usuario durante un período de 48 horas. Genera una fila por usuario principal para cada período, lo que proporciona una vista general del riesgo de la cuenta en varios tipos de detección.
En esta variación, no se requieren variables de evento. Si bien el motor de reglas filtra automáticamente las detecciones sin un usuario principal, esta búsqueda requiere un filtro explícito ($principal_user != "") para garantizar que los resultados solo incluyan datos completados. De forma predeterminada, la consulta solo devuelve resultados cuando hay una o más detecciones para un usuario determinado.
$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_user"]
$principal_user != ""
$risk = detection.detection.risk_score
match:
$principal_user over 48h
outcome:
$risk_score = 90
$cumulative_risk = sum($risk)
$upstream_rules = array_distinct($rule_name)
condition:
$cumulative_risk > 500
Panel
Esta variación se diseñó específicamente para que los paneles tracen el riesgo de los usuarios y la actividad de detección a lo largo del tiempo. Agrega datos en buckets discretos, lo que lo hace ideal para visualizar tendencias, como el volumen de reglas únicas activadas o el recuento total de detecciones por usuario.
En esta consulta, la ventana se cambia de una ventana deslizante (de salto) a una ventana de saltos de tamaño constante (by 48h). Esto garantiza que los datos se asignen a segmentos de tiempo que no se superpongan, lo que proporciona una visualización más clara para los gráficos de series temporales. Al igual que otras búsquedas no agregadas, las variables de evento no son obligatorias, y la sección outcome se expande para incluir recuentos distintos para los nombres de las reglas y los IDs de detección.
$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_user"]
$principal_user != ""
$risk = detection.detection.risk_score
match:
$principal_user by 48h
outcome:
$cumulative_risk = sum($risk)
$rule_count = count_distinct($rule_name)
$detection_count = count_distinct(detection.id)
condition:
$cumulative_risk > 500
Agregación de tácticas
Caso de uso: Identifica a los usuarios cuya actividad activó detecciones en varias tácticas distintas de MITRE ATT&CK, lo que sugiere un ciclo de vida de ataque en progreso (por ejemplo, que pasa de Acceso inicial a Exfiltración).
Lógica de la clave: Usa count_distinct($tactic) para activarse solo cuando un usuario supera un umbral específico de diferentes tácticas en un período de 48 horas.
Ejemplo: Agregación de tácticas de MITRE
Regla
rule composite_tactic_aggregation {
meta:
rule_name = "MITRE Tactic Aggregation Composite"
author = "Google Cloud Security"
description = "Composite detection that detects if a user has triggered detections over multiple mitre tactics."
severity = "Medium"
events:
$principal_user = $d.detection.detection.outcomes["principal_users"]
$tactic = $d.detection.detection.outcomes["mitre_tactic"]
$rule_name = $d.detection.detection.rule_name
match:
$principal_user over 48h
outcome:
$mitre_tactics_count = count_distinct($tactic)
$mitre_tactics = array_distinct($tactic)
$calculated_risk = 50 + (15 * $mitre_tactics_count)
$upstream_rules = array_distinct($rule_name)
condition:
$d and $mitre_tactics_count > 1 }
Buscar
En el siguiente ejemplo, se muestra una variante de búsqueda diseñada para los desarrolladores de seguridad que necesitan correlacionar las detecciones existentes y aplicar una ponderación de riesgo dinámica. Esta lógica de consulta extrae las tácticas de MITRE ATT&CK y la información del usuario de la fuente de datos detection, agrupa la actividad por el usuario principal y calcula una puntuación de riesgo personalizada en función de la diversidad de las tácticas observadas.
detection.detection.outcomes.key = "principal_users"
detection.detection.outcomes.key = "mitre_tactic"
$principal_user = detection.detection.outcomes["principal_users"]
$tactic = detection.detection.outcomes["mitre_tactic"]
$rule_name = detection.detection.rule_name
match:
$principal_user
outcome:
$mitre_tactics_count = count_distinct($tactic)
$mitre_tactics = array_distinct($tactic)
$upstream_rules = array_distinct($rule_name)
$calculated_risk = 50 + (15 * $mitre_tactics_count)
$risk_score = if($calculated_risk > 100, 100, $calculated_risk)
Panel
En el siguiente ejemplo, se ilustra una variante de Dashboards de la misma lógica de análisis de detección. Cuando se usa en los paneles de Google SecOps, esta consulta permite que los desarrolladores visualicen a los usuarios de alto riesgo correlacionando los resultados de las detecciones en diferentes reglas. La lógica extrae el usuario principal y las tácticas de MITRE, agrega los hallazgos y aplica una puntuación de riesgo limitada para ayudar a priorizar los esfuerzos de investigación directamente en un widget del panel.
detection.detection.outcomes.key = "principal_users"
detection.detection.outcomes.key = "mitre_tactic"
$principal_user = detection.detection.outcomes["principal_users"]
$tactic = detection.detection.outcomes["mitre_tactic"]
$rule_name = detection.detection.rule_name
match:
$principal_user
outcome:
$mitre_tactics_count = count_distinct($tactic)
$mitre_tactics = array_distinct($tactic)
$upstream_rules = array_distinct($rule_name)
$calculated_risk = 50 + (15 * $mitre_tactics_count)
$risk_score = if($calculated_risk > 100, 100, $calculated_risk)
```
Detecciones compuestas secuenciales
Caso de uso: Identifica patrones de ataque críticos en los que el orden de las operaciones es esencial, por ejemplo, detectar un acceso exitoso a una cuenta que se produce solo después de una serie de alertas de intentos de fuerza bruta desde la misma dirección IP.
Lógica clave: Correlaciona una detección previa con un evento de UDM sin procesar posterior uniéndolos en una variable común (por ejemplo, $bruteforce_ip) y usando una comparación de marcas de tiempo para garantizar que los eventos se produjeron en la secuencia correcta.
Las detecciones compuestas secuenciales identifican patrones de eventos relacionados en los que la secuencia de detecciones es importante, como la detección de un intento de acceso por fuerza bruta, seguido de un acceso exitoso. Estos patrones pueden involucrar varias detecciones básicas o una combinación de detecciones básicas y eventos.
Ejemplo: Intento de fuerza bruta seguido de un acceso exitoso
Regla
La siguiente regla compuesta identifica patrones de eventos relacionados en los que la secuencia es importante. Específicamente, busca una detección de fuerza bruta de Google Workspace seguida de un evento de acceso exitoso desde la misma IP de origen en un período de 24 horas.
rule composite_bruteforce_login {
meta:
rule_name = "Bruteforce Login Composite"
author = "Google Cloud Security"
description = "Detects when an IP address associated with a Workspace brute force attempt successfully logs in"
severity = "High"
events:
$bruteforce_detection.detection.detection.rule_name = /Workspace Anomalous Failed Logins/
$bruteforce_ip = $bruteforce_detection.detection.detection.variables["principal_ips"]
$login_event.metadata.product_name = "login"
$login_event.metadata.product_event_type = "login_success"
$login_event.metadata.vendor_name = "Google Workspace"
$login_ip = $login_event.principal.ip
// Ensure the brute force detection and successful login occurred from the same IP
$login_ip = $bruteforce_ip
$target_account = $login_event.target.user.email_addresses
// Ensure the brute force detection occurred before the successful login
$bruteforce_detection.detection.detection_time.seconds < $login_event.metadata.event_timestamp.seconds
match:
$bruteforce_ip over 24h
outcome:
$risk_score = 90
$principal_users = array_distinct($target_account)
condition:
$bruteforce_detection and $login_event
}
Buscar
$bruteforce_detection.detection.detection.rule_name = /Workspace Anomalous Failed Logins/
$bruteforce_ip = $bruteforce_detection.detection.detection.variables["principal_ips"]
$login_event.metadata.product_name = "login"
$login_event.metadata.product_event_type = "login_success"
$login_event.metadata.vendor_name = "Google Workspace"
$login_ip = $login_event.principal.ip
// Ensure the brute force detection and successful login occurred from the same IP
$login_ip = $bruteforce_ip
$target_account = $login_event.target.user.email_addresses
// Ensure the brute force detection occurred before the successful login
$bruteforce_detection.detection.detection_time.seconds < $login_event.metadata.event_timestamp.seconds
match:
$bruteforce_ip over 24h
outcome:
$principal_users = array_distinct($target_account)
condition:
$bruteforce_detection and $login_event
Panel
Los paneles se enfocan en visualizar los datos de eventos sin procesar, mientras que la lógica de detección compuesta correlaciona las alertas de detección existentes con los eventos posteriores. Este análisis de varias capas está optimizado para el motor de detección, en lugar de los widgets del panel en tiempo real.
Detecciones adaptadas al contexto
Caso de uso: Enriquecer las detecciones existentes con inteligencia contra amenazas externa para verificar si una alerta involucra entidades maliciosas conocidas, por ejemplo, verificar si una dirección IP marcada en una detección de seguridad también aparece en un feed de inteligencia contra amenazas de nodos de salida de TOR global.
Lógica de claves: Usa reglas compuestas para unir los hallazgos de detección con los datos del GLOBAL_CONTEXTgrafo (por ejemplo, los feeds de Google Cloud inteligencia contra amenazas) a través de la correlación de un atributo compartido, como una dirección IP.
Las detecciones compuestas adaptadas al contexto enriquecen las detecciones con contexto adicional, como las direcciones IP que se encuentran en los feeds de amenazas.
Ejemplo: Enriquecimiento de la inteligencia contra amenazas
Regla
La siguiente regla compuesta agrega automáticamente contexto adicional del feed de inteligencia de TOR a tus detecciones existentes. Correlaciona una dirección IP encontrada en una detección anterior con el feed de nodos de salida de TOR para elevar la gravedad y la puntuación de riesgo del hallazgo.
rule composite_tor_enrichment {
meta:
rule_name = "Detection with IP from TOR Feed"
author = "Google Cloud Security"
description = "Adds additional context from the TOR intel feed to detections"
severity = "High"
events:
$rule_name = $d.detection.detection.rule_name
$gcti.graph.metadata.entity_type = "IP_ADDRESS"
$gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence"
$gcti.graph.metadata.source_type = "GLOBAL_CONTEXT"
$gcti.graph.metadata.product_name = "GCTI Feed"
$gcti.graph.metadata.feed = "Tor Exit Nodes"
$detection_ip = $d.detection.detection.variables["principal_ips"]
$detection_ip = $gcti.graph.entity.ip
match:
$detection_ip, $rule_name over 1h
outcome:
$risk_score = 80
condition:
$d and $gcti
}
Buscar
$rule_name = $d.detection.detection.rule_name
$gcti.graph.metadata.entity_type = "IP_ADDRESS"
$gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence"
$gcti.graph.metadata.source_type = "GLOBAL_CONTEXT"
$gcti.graph.metadata.product_name = "GCTI Feed"
$gcti.graph.metadata.feed = "Tor Exit Nodes"
$detection_ip = $d.detection.detection.variables["principal_ips"]
$detection_ip = $gcti.graph.entity.ip
match:
$detection_ip, $rule_name over 1h
condition:
$d and $gcti
Panel
Detecciones de coocurrencia
Caso de uso: Detecta una combinación de tácticas relacionadas activadas por la misma entidad en un período específico, por ejemplo, identificar a un usuario que activó una detección de elevación de privilegios y una detección de robo de datos en un plazo de 48 horas.
Lógica clave: Usa una forma de agregación para correlacionar varios tipos de detección distintos uniéndolos en una variable de entidad compartida (por ejemplo, $pe_user) dentro de la sección match.
Las detecciones compuestas de simultaneidad son una forma de agregación que puede detectar una combinación de eventos relacionados, como una combinación de detecciones de elevación de privilegios y robo de datos activadas por un usuario.
Ejemplo: Coocurrencia de elevación de privilegios y exfiltración
Regla
La siguiente regla compuesta busca una secuencia o combinación específica de detecciones (elevación de privilegios seguido de exfiltración) asociadas con el mismo usuario en un período de 48 horas.
rule composite_privesc_exfil_sequential {
meta:
rule_name = "Privilege Escalation and Exfiltration Composite"
author = "Google Cloud Security"
description = "Looks for a detection sequence of privilege escalation followed by exfiltration."
severity = "High"
events:
$privilege_escalation.detection.detection.rule_labels["tactic"] = "TA0004"
$exfiltration.detection.detection.rule_labels["tactic"] = "TA0010"
$privesc_user = $privilege_escalation.detection.detection.variables["principal_users"]
$exfil_user = $exfiltration.detection.detection.variables["principal_users"]
$privesc_user = $exfil_user
$privilege_escalation.detection.detection_time.seconds < $exfiltration.detection.detection_time.seconds
match:
$privesc_user over 48h
outcome:
$risk_score = 75
$privesc_rules = array_distinct($privilege_escalation.detection.detection.rule_name)
$exfil_rules = array_distinct($exfiltration.detection.detection.rule_name)
condition:
$privilege_escalation and $exfiltration
}
Buscar
$privilege_escalation.detection.detection.rule_labels["tactic"] = "TA0004"
$exfiltration.detection.detection.rule_labels["tactic"] = "TA0010"
$privesc_user = $privilege_escalation.detection.detection.variables["principal_users"]
$exfil_user = $exfiltration.detection.detection.variables["principal_users"]
$privesc_user = $exfil_user
$privilege_escalation.detection.detection_time.seconds < $exfiltration.detection.detection_time.seconds
match:
$privesc_user over 48h
outcome:
$privesc_rules = array_distinct($privilege_escalation.detection.detection.rule_name)
$exfil_rules = array_distinct($exfiltration.detection.detection.rule_name)
condition:
$privilege_escalation and $exfiltration
Panel
Administración de resultados y variables
En esta sección, se muestran ejemplos de cómo calcular el riesgo y normalizar los datos para el consumo downstream.
Sección Consultas con outcome
Puedes agregar la sección opcional outcome en una regla de YARA-L 2.0 para extraer información adicional de cada detección. En la sección condition, también puedes especificar condicionales en las variables de resultado. Puedes usar la sección outcome de una regla de detección
para establecer variables para el consumo downstream. Por ejemplo, puedes establecer una
puntuación de gravedad según los datos de los eventos que se analizan.
Para obtener más información, consulta lo siguiente:
- Sintaxis de la sección de resultados
- Sintaxis de la sección de condiciones
- Sección Análisis adaptado al contexto,
outcome
Condicionales de resultados
Caso de uso: Filtra las detecciones según las puntuaciones de riesgo calculadas para reducir el ruido y garantizar que solo los eventos de alta confianza o gravedad activen alertas. Esto es útil para suprimir la actividad de bajo riesgo que no cumple con un umbral comercial específico.
Lógica clave: Define variables en la sección outcome con matemáticas condicionales (por ejemplo, agregar riesgo según el tamaño del archivo o la hora del día) y, luego, hace referencia a esas variables en la sección condition para controlar la detección.
Ejemplo: Filtra por la puntuación de riesgo calculada
Regla
En la sección condition, puedes usar variables outcome que se definieron en la sección outcome. En el siguiente ejemplo, se muestra cómo filtrar las puntuaciones de riesgo para reducir el ruido en las detecciones con condicionales de resultado.
rule OutcomeConditionalRule {
meta:
author = "alice@example.com"
description = "Rule that uses outcome conditionals"
events:
$u.metadata.event_type = "FILE_COPY"
$u.principal.file.size = $file_size
$u.principal.hostname = $hostname
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week($u.metadata.collected_timestamp.seconds)
outcome:
$risk_score =
if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices
condition:
$u and $risk_score >= 10
}
Buscar
metadata.event_type = "FILE_COPY"
principal.file.size = $file_size
principal.hostname = $hostname
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.collected_timestamp.seconds)
outcome:
$risk_score =
if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices
Panel
Esta consulta agrega la variable de resultado $hostname para visualizar qué hosts están asociados con cada puntuación de riesgo.
metadata.event_type = "FILE_COPY"
principal.file.size = $file_size
principal.hostname = $hostname
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.collected_timestamp.seconds)
outcome:
$host = $hostname
$risk_score =
if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices
Búsqueda de un solo evento con resultado
Caso de uso: Enriquecer las detecciones en un momento determinado con contexto inmediato, como asignar etiquetas de gravedad según listas de usuarios o atributos de archivos sin necesidad de una ventana temporal ni correlación de eventos
Lógica clave: Usa la sección outcome en una regla que carece de una sección match. Esto te permite extraer metadatos y aplicar lógica condicional (por ejemplo, verificar un usuario con una lista de referencia) para cada evento individual que cumpla con los criterios.
Ejemplo: Etiquetado de gravedad en un momento determinado
Regla
En el siguiente ejemplo, se muestra cómo usar la sección outcome en una regla de un solo evento para establecer variables para el consumo posterior, como establecer una puntuación de gravedad según el usuario específico y el tamaño del archivo involucrados en un evento de copia de archivos.
rule OutcomeRuleSingleEvent {
meta:
author = "alice@example.com"
events:
$u.metadata.event_type = "FILE_COPY"
$u.principal.file.size = $file_size
$u.principal.hostname = $hostname
outcome:
$suspicious_host = $hostname
$admin_severity = if($u.principal.user.userid in %admin_users, "SEVERE", "MODERATE")
$severity_tag = if($file_size > 1024, $admin_severity, "LOW")
condition:
$u
}
Buscar
En el siguiente ejemplo, se identifican los eventos de creación de archivos y se usa la sección outcome para asignar de forma dinámica niveles de gravedad a cada resultado. A diferencia de las reglas de eventos múltiples, esta búsqueda sin agregar no requiere variables de eventos ni una sección match. En cambio, procesa cada registro de forma individual para generar 1 row per event, enriquecido con lógica personalizada basada en el tamaño del archivo y los permisos del usuario.
metadata.event_type = "FILE_CREATION"
principal.file.size = $file_size
principal.hostname = $hostname
outcome:
$suspicious_host = $hostname
$admin_severity = if(principal.user.userid in %a1, "SEVERE", "MODERATE")
$severity_tag = if($file_size > 1024, $admin_severity, "LOW")
Panel
Una variante del panel no es aplicable para este ejemplo, ya que la intención principal es etiquetar y enriquecer eventos individuales. Si bien un panel podría agregar estos eventos (por ejemplo, calcular el recuento total de eventos por etiqueta de gravedad), hacerlo ocultaría el detalle granular a nivel de la fila que esta búsqueda no agregada está diseñada para encontrar.
Puntuación de riesgo basada en la red
Caso de uso: Identifica las transferencias de datos de alto riesgo calculando el volumen acumulativo del tráfico de red en un grupo de eventos. Esto te permite identificar amenazas en las que el umbral de datos totales supera un límite específico (por ejemplo, 1024 bytes) y, al mismo tiempo, tener en cuenta la gravedad de la vulnerabilidad de los activos involucrados.
Lógica clave: Usa la función de agregación sum() en la sección outcome para combinar sent_bytes y received_bytes en todos los eventos de un período match. En el caso de las reglas, la consulta usa una sentencia if para aplicar una puntuación de riesgo más alta si esa suma supera un umbral definido.
Ejemplo: Regla de puntuación de riesgo basada en la red
Regla
En el siguiente ejemplo, se muestra cómo usar la sección outcome para calcular una puntuación de riesgo dinámica basada en la actividad de red. Al sumar los bytes totales transferidos en un grupo de eventos, la regla aplica una prioridad más alta a las coincidencias que superan un umbral de datos específico (1024 bytes) y, al mismo tiempo, tiene en cuenta la gravedad de la vulnerabilidad del activo involucrado.
rule OutcomeRuleMultiEvent {
meta:
author = "alice@example.com"
events:
$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname
$severity = $asset_context.graph.entity.asset.vulnerabilities.severity
match:
$hostname over 5m
outcome:
$total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)
$risk_score = if($total_network_bytes > 1024, 100, 50) +
max(
if($severity = "HIGH", 10)
+ if($severity = "MEDIUM", 5)
+ if($severity = "LOW", 1)
)
$asset_id_list =
array(
if($u.principal.asset_id = "",
"Empty asset id",
$u.principal.asset_id
)
)
$asset_id_distinct_list = array_distinct($u.principal.asset_id)
$asset_id_count = count($u.principal.asset_id)
$asset_id_distinct_count = count_distinct($u.principal.asset_id)
condition:
$u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}
Buscar
En el siguiente ejemplo, se muestra una variante de búsqueda que correlaciona los eventos de red del UDM con el contexto del recurso del Entity Context Graph (ECG). Utiliza una ventana de match de 5 minutos para agregar el tráfico de red por nombre de host, calcula una puntuación de riesgo según el volumen de datos y la gravedad de la vulnerabilidad, y aplica un filtro condicional para excluir IDs de activos específicos del conjunto de resultados final.
$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname
$severity = $asset_context.graph.entity.asset.vulnerabilities.severity
match:
$hostname over 5m
outcome:
$total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)
$risk_score = if($total_network_bytes > 1024, 100, 50) +
max(
if($severity = "HIGH", 10)
+ if($severity = "MEDIUM", 5)
+ if($severity = "LOW", 1)
)
$asset_id_list =
array(
if($u.principal.asset_id = "",
"Empty asset id",
$u.principal.asset_id
)
)
$asset_id_distinct_list = array_distinct($u.principal.asset_id)
$asset_id_count = count($u.principal.asset_id)
$asset_id_distinct_count = count_distinct($u.principal.asset_id)
condition:
$u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
Panel
En el siguiente ejemplo, se ilustra una variante de Dashboards que enriquece la telemetría de red en tiempo real con datos de vulnerabilidad de los recursos. Al correlacionar los nombres de host en un período de 5 minutos, esta consulta permite que los desarrolladores creen widgets de panel que visualicen los niveles de riesgo de los activos. La lógica ajusta de forma dinámica una puntuación de riesgo según la capacidad de procesamiento de la red y la vulnerabilidad de mayor gravedad que se encuentre en el recurso, lo que proporciona una vista priorizada de los sistemas potencialmente comprometidos.
$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname
$severity = $asset_context.graph.entity.asset.vulnerabilities.severity
match:
$hostname over 5m
outcome:
$total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)
$risk_score = if($total_network_bytes > 1024, 100, 50) +
max(
if($severity = "HIGH", 10)
+ if($severity = "MEDIUM", 5)
+ if($severity = "LOW", 1)
)
$asset_id_list =
array(
if($u.principal.asset_id = "",
"Empty asset id",
$u.principal.asset_id
)
)
$asset_id_distinct_list = array_distinct($u.principal.asset_id)
$asset_id_count = count($u.principal.asset_id)
$asset_id_distinct_count = count_distinct($u.principal.asset_id)
condition:
$u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
Refactoriza una regla de outcome de varios eventos (antes de la refactorización)
Caso de uso: Mejora el rendimiento del sistema y reduce la latencia de procesamiento convirtiendo las reglas de varios eventos en reglas de un solo evento. Esto es ideal para las reglas que se diseñaron originalmente con una sección de coincidencias solo para habilitar la sección de resultados, pero que en realidad no requieren correlación entre varios eventos distintos.
Lógica clave: Quita la sección match y cualquier función de agregación (por ejemplo, max(), sum() o count()) de la sección outcome. Esta transición cambia la regla de agrupar eventos a lo largo del tiempo a evaluar cada evento de forma individual a medida que llega.
sección match) y reglas de eventos múltiples (reglas con una sección match).
Puedes usar la sección outcome para las reglas de un solo evento (reglas sin una sección ) y para las reglas de varios eventos.
Si anteriormente diseñaste una regla para que fuera de varios eventos solo para poder
usar la sección de resultados, puedes refactorizar esas reglas de forma opcional borrando
la sección match para mejorar el rendimiento. Ten en cuenta que, como tu regla ya no tiene una sección match que aplique la agrupación, es posible que recibas más detecciones.
Ejemplo: Refactorización del resultado (antes de la refactorización)
Regla
En el siguiente ejemplo, se muestra una regla de resultado de varios eventos que usa solo una variable de evento. Debido a que usa una sección match, el motor de reglas debe agrupar los eventos en un período de 5 minutos antes de calcular el resultado, lo que consume más recursos que una evaluación de un solo evento.
rule OutcomeMultiEventPreRefactor {
meta:
author = "alice@example.com"
description = "Outcome refactor rule, before the refactor"
events:
$u.udm.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
$risk_score = max(if($hostname = "my-hostname", 100, 50))
condition:
$u
}
Buscar
Consulta de estadísticas equivalente
events:
$u.udm.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
$risk_score = max(if($hostname = "my-hostname", 100, 50))
condition:
$u
Panel
events:
$u.udm.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
$risk_score = max(if($hostname = "my-hostname", 100, 50))
condition:
$u
Refactoriza una regla de outcome de varios eventos (después de la refactorización)
Caso de uso: Finalizar la optimización de una búsqueda para mejorar la velocidad de procesamiento Al quitar el requisito de agrupación, la consulta ahora activa una detección inmediatamente después de la llegada de un solo evento coincidente, lo que es significativamente más eficiente para el motor de reglas.
Lógica clave: Borra la sección match y quita la función aggregate (por ejemplo, max()) de la asignación de la variable outcome. La lógica dentro de la sentencia if sigue siendo la misma, pero ahora se aplica a un solo evento en lugar de a un grupo.
Puedes refactorizar la consulta borrando la sección match. Nota: También debes quitar el agregado en la sección outcome porque la búsqueda ahora es de un solo evento. Para obtener más información sobre las agregaciones, consulta Agregaciones de resultados.
Ejemplo: Refactorización de resultados
Regla
rule OutcomeSingleEventPostRefactor {
meta:
author = "alice@example.com"
description = "Outcome refactor rule, after the refactor"
events:
$u.udm.principal.hostname = $hostname
// We deleted the match section.
outcome:
// We removed the max() aggregate.
$risk_score = if($hostname = "my-hostname", 100, 50)
condition:
$u
}
Buscar
events:
$u.udm.principal.hostname = $hostname
outcome:
$risk_score = if($hostname = "my-hostname", 100, 50)
Panel
events:
$u.udm.principal.hostname = $hostname
outcome:
$risk_score = if($hostname = "my-hostname", 100, 50)
Asignación de función a marcador de posición
Caso de uso: Normalizar los datos (por ejemplo, estandarizar los dominios de correo electrónico) para verificar que la agrupación en la sección de coincidencias sea precisa
Lógica clave: Asigna el resultado de re.capture() o strings.concat() a una variable de marcador de posición.
Ejemplo: Asignación de variables de función a marcador de posición
Puedes asignar una variable de marcador de posición al resultado de una llamada a función y usarla en otras secciones de la regla, como las secciones match, outcome o condition.
Regla
rule FunctionToPlaceholderRule {
meta:
author = "alice@example.com"
description = "Rule that uses function to placeholder assignments"
events:
$u.metadata.event_type = "EMAIL_TRANSACTION"
// Use function-placeholder assignment to extract the
// address from an email.
// address@website.com -> address
$email_to_address_only = re.capture($u.network.email.to , "(.*)@")
// Use function-placeholder assignment to normalize an email:
// address@-> address@company.com
$email_from_normalized = strings.concat(
re.capture($u.network.email.from , "(.*)@"),
"@company.com"
)
// Use function-placeholder assignment to get the day of the week of the event.
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week($u.metadata.event_timestamp.seconds)
match:
// Use placeholder (from function-placeholder assignment) in match section.
// Group by the normalized from email, and expose it in the detection.
$email_from_normalized over 5m
outcome:
// Use placeholder (from function-placeholder assignment) in outcome section.
// Assign more risk if the event happened on weekend.
$risk_score = max(
if($dayofweek = 1 or $dayofweek = 7, 10, 0)
)
condition:
// Use placeholder (from function-placeholder assignment) in condition section.
// Match if an email was sent to multiple addresses.
#email_to_address_only > 1
}
Buscar
metadata.event_type = "EMAIL_TRANSACTION"
// Use function-placeholder assignment to extract the
// address from an email.
// address@website.com -> address
$email_to_address_only = re.capture(network.email.from , "(.*)@")
// Use function-placeholder assignment to normalize an email:
// address@??? -> address@company.com
$email_from_normalized = strings.concat(
re.capture(network.email.to , "(.*)@"),
"@company.com"
)
// Use function-placeholder assignment to get the day of the week of the event.
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.event_timestamp.seconds)
match:
// Use placeholder (from function-placeholder assignment) in match section.
// Group by the normalized from email, and expose it in the detection.
$email_from_normalized over 5m
outcome:
// Use placeholder (from function-placeholder assignment) in outcome section.
// Assign more risk if the event happened on weekend.
$risk_score = max(
if($dayofweek = 1 or $dayofweek = 7, 10, 0)
)
condition:
// Use placeholder (from function-placeholder assignment) in condition section.
// Match if an email was sent to multiple addresses.
#email_to_address_only > 1
Panel
En el siguiente ejemplo, se muestra una variante de Dashboards optimizada para la visualización de series temporales. Con una ventana de saltos de tamaño constante de un día, en lugar de un nivel de detalle a nivel de minutos, esta consulta genera puntos de datos estables y no superpuestos, ideales para generar gráficos de las puntuaciones de riesgo durante un período prolongado. La lógica normaliza las entidades de correo electrónico y aplica ponderaciones de riesgo más altas a las transacciones de fin de semana, lo que proporciona una tendencia diaria clara de la actividad sospechosa por correo electrónico para la supervisión a largo plazo.
metadata.event_type = "EMAIL_TRANSACTION"
// Use function-placeholder assignment to extract the
// address from an email.
// address@website.com -> address
$email_to_address_only = re.capture(network.email.from , "(.*)@")
// Use function-placeholder assignment to normalize an email:
// address@??? -> address@company.com
$email_from_normalized = strings.concat(
re.capture(network.email.to , "(.*)@"),
"@company.com"
)
// Use function-placeholder assignment to get the day of the week of the event.
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.event_timestamp.seconds)
match:
// Use placeholder (from function-placeholder assignment) in match section.
// Group by the normalized from email, and expose it in the detection.
$email_from_normalized over 5m
outcome:
// Use placeholder (from function-placeholder assignment) in outcome section.
// Assign more risk if the event happened on weekend.
$risk_score = max(
if($dayofweek = 1 or $dayofweek = 7, 10, 0)
)
condition:
// Use placeholder (from function-placeholder assignment) in condition section.
// Match if an email was sent to multiple addresses.
#email_to_address_only > 1
Optimización y filtrado
La optimización eficaz de las reglas se basa en el filtrado preciso de datos para garantizar que el motor de detección solo procese información significativa. Si excluyes los datos "ruidosos" o incompletos, puedes mejorar significativamente el rendimiento de las reglas y asegurarte de que las alertas generadas sean prácticas.
| Tema | Ejemplos |
|---|---|
| Exclusión de valores cero | Exclusión de valores cero explícitos e implícitos |
Exclusión de valores cero
Caso de uso: Asegúrate de que la regla sea precisa y reduce los falsos positivos filtrando de forma explícita las cadenas vacías, los valores nulos o las cuentas de marcador de posición genéricas (por ejemplo, "Invitado") que no proporcionan datos de seguridad prácticos.
Lógica clave: Aprovecha el filtrado implícito de valores cero del motor de reglas para las variables que se usan en la sección match, mientras que usa operadores de desigualdad explícitos (!= "") para otros campos de eventos y, así, garantizar que solo los datos completados activen una detección.
El motor de reglas filtra de forma implícita los valores cero para todos los marcadores de posición que se usan en la sección match. Usa la opción allow_zero_values para inhabilitar la función. Sin embargo, para otros campos de eventos a los que se hace referencia, los valores cero no se excluyen, a menos que especifiques explícitamente esas condiciones. Para obtener más información, consulta Valores cero en la sección de coincidencias.
Ejemplo: Exclusión explícita e implícita de valores cero
Regla
rule ExcludeZeroValues {
meta:
author = "alice@example.com"
events:
$e1.metadata.event_type = "NETWORK_DNS"
$e1.principal.hostname = $hostname
// $e1.principal.user.userid may be empty string.
$e1.principal.user.userid != "Guest"
$e2.metadata.event_type = "NETWORK_HTTP"
$e2.principal.hostname = $hostname
// $e2.target.asset_id cannot be empty string as explicitly specified.
$e2.target.asset_id != ""
match:
// $hostname cannot be empty string. The rule behaves as if the
// predicate, `$hostname != ""` was added to the events section, because
// `$hostname` is used in the match section.
$hostname over 1h
condition:
$e1 and $e2
}
Buscar
Debes indicar de forma explícita que hostname no puede ser una cadena vacía, ya que no hay un filtro implícito de valor cero para los marcadores de posición en la sección match.
$e1.metadata.event_type = "NETWORK_DNS"
$e1.principal.hostname = $hostname
// $e1.principal.user.userid may be empty string.
$e1.principal.user.userid != "Guest"
$e2.metadata.event_type = "NETWORK_HTTP"
$e2.principal.hostname = $hostname
// $e2.target.asset_id and hostname cannot be empty string as explicitly specified.
$e2.target.asset_id != ""
$hostname != ""
match:
$hostname over 1h
Panel
Debes indicar de forma explícita que hostname no puede ser una cadena vacía, ya que no hay un filtro de valor cero implícito para los marcadores de posición en la sección match.
$e1.metadata.event_type = "NETWORK_DNS"
$e1.principal.hostname = $hostname
// $e1.principal.user.userid may be empty string.
$e1.principal.user.userid != "Guest"
$e2.metadata.event_type = "NETWORK_HTTP"
$e2.principal.hostname = $hostname
// $e2.target.asset_id and hostname cannot be empty string as explicitly specified.
$e2.target.asset_id != ""
$hostname != ""
match:
$hostname over 1h
¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.