Cómo crear reglas de detección compuestas

Compatible con:

En este documento, se proporciona una guía técnica para crear una regla compuesta en la plataforma de Google Security Operations, un proceso que implica conectar varias reglas de YARA-L 2.0 para identificar patrones de ataque complejos. Las detecciones compuestas se estructuran como reglas de varios eventos, y mantienen la misma sintaxis fundamental que las reglas estándar de un solo evento. Para obtener más información, consulta Descripción general de las detecciones compuestas.

Cómo interpretar la estructura de las reglas

Las reglas de detección compuestas siempre son reglas de varios eventos y siguen la misma estructura y sintaxis que una regla de un solo evento.

Una regla compuesta tiene los siguientes componentes esenciales:

  • Sección events: Define tus entradas, es decir, las detecciones o los eventos específicos que analiza la regla.

  • Sección match: Especifica cómo se deben conectar las entradas durante un período definido.

  • Sección condition: Contiene la lógica final que determina si los eventos unidos cumplen con los criterios para activar una alerta.

Cómo definir las entradas en la sección events

El primer paso para crear una regla de detección compuesta es definir las entradas de la regla en la sección events. Las entradas de las reglas compuestas provienen de colecciones, que almacenan las detecciones generadas por otras consultas. Google SecOps proporciona los siguientes dos métodos para acceder a los datos de las colecciones.

Cómo hacer referencia al contenido de detección con variables o etiquetas meta

Para acceder a los datos de una detección sin hacer referencia a los eventos originales del UDM, puedes usar variables outcome, variables match o etiquetas meta. Recomendamos este enfoque porque proporciona mayor flexibilidad y mejor compatibilidad en diferentes tipos de reglas.

Por ejemplo, varias reglas pueden almacenar una cadena (como una URL, un nombre de archivo o una clave de registro) en una variable outcome común si buscas esa cadena en diferentes contextos. Para acceder a esta cadena desde una regla compuesta, comienza con detection y ubica la información pertinente con elementos del recurso Collection.

Ejemplo: Supongamos que una regla de detección produce la siguiente información:

  • Variable de resultado: dest_domain = "cymbal.com"

  • Campo de UDM: target.hostname = "cymbal.com"

En la regla compuesta, puedes acceder a estos datos con las siguientes rutas de acceso:

  • detection.detection.outcomes["dest_domain"] para acceder a la variable de resultado dest_domain

  • detection.collection_elements.references.event.target.hostname para acceder al campo de UDM target.hostname

  • detection.time_window.start_time.seconds para acceder a la marca de tiempo de inicio de la detección

La API de Collection y la API de SecurityResult proporcionan acceso a lo siguiente:

  • Metadatos de detección y valores de resultado (detection.detection)
  • Eventos subyacentes del UDM de las reglas a las que se hace referencia (collection_elements)

Cómo hacer referencia al contenido de detección con el ID o el nombre de la regla

Puedes hacer referencia a una regla por su nombre o ID. Recomendamos este enfoque cuando tu lógica de detección depende de reglas específicas y deseas reducir los datos analizados solo a los resultados de esas reglas. Hacer referencia a las reglas pertinentes por nombre o ID mejora el rendimiento y evita los tiempos de espera, ya que reduce los datos analizados. Por ejemplo, puedes consultar directamente campos como target.url o principal.ip de una detección anterior conocida.

  • Haz referencia a una regla por su ID (recomendado): Usa el campo detection.detection.rule_id para hacer referencia a una regla por su ID. Puedes encontrar el ID de la regla en la URL de la regla en Google SecOps. Las reglas generadas por el usuario tienen IDs con el formato ru_UUID, mientras que las detecciones seleccionadas tienen IDs con el formato ur_UUID. Por ejemplo:

    detection.detection.rule_id = "ru_e0d3f371-6832-4d20-b0ad-1f4e234acb2b"

  • Haz referencia a una regla por su nombre: Usa el campo detection.detection.rule_name para hacer referencia a una regla por su nombre. Puedes especificar el nombre exacto de la regla o usar una expresión regular para que coincida. Por ejemplo:

    • detection.detection.rule_name = "My Rule Name"
    • detection.detection.rule_name = "/PartOfName/"

Cómo unir entradas en la sección match

Para conectar detecciones, eventos o entidades relacionados en una regla compuesta, define la sección match con las variables definidas en la sección events. Estas variables pueden incluir etiquetas de reglas, variables de resultado, variables de coincidencia, campos de detección o elementos de colección.

Para obtener información sobre la sintaxis, consulta Sintaxis de la sección Match.

Reglas compuestas: intervalos de tiempo y ventanas de salto

Las reglas compuestas hacen coincidir las detecciones y los eventos con un intervalo de tiempo en lugar de un solo punto en el tiempo. Coinciden con una ventana de salto compuesta si la ventana de tiempo de detección de entrada se superpone con esa ventana de salto (por ejemplo, la actividad estuvo activa durante ese bloque de tiempo).

Una sola detección puede activar varias alertas si abarca el límite entre ventanas de salto adyacentes (debido a las demoras en la canalización, estas coincidencias históricas aparecen más tarde). Específicamente, una ventana de salto de regla compuesta activa una coincidencia si la ventana de tiempo de detección de entrada (WindowStart a WindowEnd) se superpone con la ventana de salto.

Por ejemplo:

  1. Una regla compuesta tiene ventanas de salto de 60 minutos: Salto 1 (18:58 - 19:58) y Salto 2 (19:58 - 20:58).
  2. Una detección de productor ascendente tiene una ventana de 19:57:54 a 20:56:54 (duración de 59 minutos).
  3. Como la ventana del productor comenzó a las 19:57:54 (6 segundos antes de que finalizara el Salto 1) y finalizó a las 20:56:54 (durante el Salto 2), se superpone con ambas ventanas de salto.
  4. Esto activa dos detecciones compuestas (una para el Salto 1 y otra para el Salto 2), lo que ayuda a evitar falsos negativos. Si la regla del productor no coincidiera con la superposición, la detección superpuesta parcialmente no se consideraría para el Salto 1 ni el Salto 2, y se perdería la correlación entre la detección y otros eventos.

Para obtener más información y ejemplos sobre cómo especificar ventanas de salto, consulta Ventanas de salto.

Cómo definir la sección condition

Define la sección condition para evaluar los resultados de la sección match. Si la condición es true, se genera una alerta. Para obtener información sobre la sintaxis, consulta Sintaxis de la sección Condition.

Cómo aplicar técnicas avanzadas a reglas compuestas

En esta sección, se explica cómo aplicar técnicas avanzadas mientras se crean reglas compuestas.

Cómo combinar eventos y detecciones

Las reglas compuestas pueden combinar varias fuentes de datos, incluidos eventos del UDM, datos de gráficos de entidades y campos de detección. Deben aplicarse las siguientes pautas:

  • Usa variables distintas por fuente: Asigna variables de eventos únicas a cada fuente de datos (por ejemplo, $e para eventos, $d para detecciones), en la que la fuente de datos incluye eventos, entidades y detecciones.

  • Une fuentes en un contexto compartido: Conecta fuentes de datos con valores comunes, como IDs de usuario, direcciones IP o nombres de dominio en las condiciones de tu regla.

  • Define una ventana de coincidencia: Siempre incluye una cláusula match con una ventana de tiempo que no supere las 48 horas.

Ejemplo: Cómo combinar eventos y detecciones

rule CheckCuratedDetection_with_EDR_and_EG {
  meta:
    author = "noone@cymbal.com"
  events:
    $d.detection.detection.rule_name = /SCC: Custom Modules: Configurable Bad Domain/
    $d.detection.collection_elements.references.event.network.dns.questions.name = $domain
    $d.detection.collection_elements.references.event.principal.asset.hostname = $hostname

    $e.metadata.log_type = "LIMACHARLIE_EDR"
    $e.metadata.product_event_type = "NETWORK_CONNECTIONS"
    $domain = re.capture($e.principal.process.command_line, "\\s([a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+)$")
    $hostname = re.capture($e.principal.hostname, "([^.]*)")

    $prevalence.graph.metadata.entity_type = "DOMAIN_NAME"
    $prevalence.graph.metadata.source_type = "DERIVED_CONTEXT"
    $prevalence.graph.entity.hostname = $domain
    $prevalence.graph.entity.domain.prevalence.day_count = 10
    $prevalence.graph.entity.domain.prevalence.rolling_max <= 5
    $prevalence.graph.entity.domain.prevalence.rolling_max > 0

  match:
    $hostname over 1h

  outcome:
    $risk_score = 80
    $CL_target = array($domain)

  condition:
    $e and $d and $prevalence
}

Cómo crear detecciones compuestas secuenciales

Las detecciones compuestas secuenciales identifican patrones de eventos relacionados en los que la secuencia de detecciones es importante, como una detección de intento de acceso por fuerza bruta, seguida de un acceso exitoso. Estos patrones pueden combinar varias detecciones base, eventos sin procesar del UDM o ambos.

Para crear una detección compuesta secuencial, debes aplicar ese orden en tu regla. Para aplicar la secuencia esperada, usa uno de los siguientes métodos:

  • Ventanas deslizantes: Define la secuencia de detecciones con ventanas deslizantes en tus condiciones match.

  • Comparaciones de marcas de tiempo: Compara las marcas de tiempo de las detecciones dentro de la lógica de tu regla para verificar que ocurran en el orden seleccionado.

Ejemplo: Detecciones compuestas secuenciales

events:
    $d1.detection.detection.rule_name = "fileEvent_rule"
    $userid = $d1.detection.detection.outcomes["user"]
    $hostname = $d1.detection.detection.outcomes["hostname"]

    $d2.detection.detection.rule_name = "processExecution_rule"
    $userid = $d2.detection.detection.outcomes["user"]
    $hostname = $d2.detection.detection.outcomes["hostname"]

    $d3.detection.detection.rule_name = "networkEvent_rule"
    $userid = $d3.detection.detection.outcomes["user"]
    $hostname = $d3.detection.detection.outcomes["hostname"]

$d3.detection.collection_elements.references.event.metadata.event_timestamp.seconds > $d2.detection.collection_elements.references.event.metadata.event_timestamp.seconds

  match:
    $userid over 24h after $d1

¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.