Crea consultas de varias etapas en YARA-L
En este documento, se describe cómo las consultas de varias etapas en YARA-L te permiten ingresar el resultado de una etapa de la consulta directamente en la entrada de una etapa posterior. Este proceso te brinda un mayor control sobre la transformación de datos que una sola consulta monolítica.
Integrar búsquedas de varias etapas con funciones existentes
Las consultas de varias etapas funcionan en conjunto con las siguientes funciones existentes en Google Security Operations:
Reglas de detección compuestas: Las consultas de varias etapas complementan las reglas de detección compuestas. A diferencia de las reglas compuestas, las búsquedas de varias etapas que usan Search pueden devolver resultados en tiempo real.
Períodos y reglas de varios eventos: Puedes usar consultas de varias etapas para detectar anomalías comparando diferentes períodos en tus datos. Por ejemplo, puedes usar las etapas iniciales de tu búsqueda para establecer un valor de referencia durante un período prolongado y, luego, usar una etapa posterior para evaluar la actividad reciente en comparación con ese valor de referencia. También puedes usar reglas de varios eventos para crear un tipo de comparación similar.
Las consultas de varias etapas en YARA-L son compatibles con los paneles y la búsqueda.
Las uniones ayudan a correlacionar datos de múltiples fuentes para proporcionar más contexto para una investigación. Al vincular eventos, entidades y otros datos relacionados, puedes investigar situaciones de ataque complejas. Para obtener más información, consulta Cómo usar uniones en la Búsqueda.
Cómo definir la sintaxis de YARA-L de varias etapas
A medida que configures una consulta de varias etapas, ten en cuenta lo siguiente:
- Etapa de límite: Las consultas de varias etapas deben contener entre 1 y 4 etapas con nombre, además de la etapa raíz.
- Sintaxis de orden: Siempre define la sintaxis de la etapa con nombre antes de definir la sintaxis de la etapa raíz.
Crea una consulta de YARA-L de varias etapas
Para crear una búsqueda de YARA-L de varias etapas, completa los siguientes pasos.
Estructura y sintaxis de la etapa
Ve a Investigación > Búsqueda. Sigue estos requisitos estructurales cuando definas las etapas de tu consulta:
Sintaxis: Usa la siguiente sintaxis para nombrar cada etapa y separarla de otras etapas:
stage <stage name> { }
Llaves: Coloca toda la sintaxis de la etapa dentro de llaves {}.
Orden: Define la sintaxis para todas las etapas con nombre antes de definir la etapa raíz.
Referencias: Cada etapa puede hacer referencia a etapas definidas anteriormente en la consulta.
Etapa raíz: Una consulta debe tener una etapa raíz, que se procesa después de todas las etapas con nombre.
La siguiente etapa de ejemplo, daily_stats, recopila estadísticas diarias de la red:
stage daily_stats {
metadata.event_type = "NETWORK_CONNECTION"
$source = principal.hostname
$target = target.ip
$source != ""
$target != ""
$total_bytes = cast.as_int(network.sent_bytes + network.received_bytes)
match:
$source, $target by day
outcome:
$exchanged_bytes = sum($total_bytes)
}
Salida de la etapa de acceso
Se puede acceder al resultado de una etapa con nombre en etapas posteriores a través de los campos de etapa. Los campos de etapa corresponden a las variables match y outcome de la etapa, y se pueden usar de manera similar a los campos del modelo de datos unificado (UDM).
Usa la siguiente sintaxis para acceder a un campo de etapa:
$<stage name>.<variable name>
Marcas de tiempo de la ventana de acceso (opcional)
Si una etapa con nombre usa una ventana de salto, deslizante o rotativa, accede al inicio y al final de la ventana para cada fila de salida con estos campos reservados:
$<stage name>.window_start$<stage name>.window_end
window_start y window_end son campos de números enteros expresados en segundos desde la época de Unix. Las ventanas en diferentes etapas pueden variar en tamaño.
Limitaciones
Las consultas de varias etapas tienen las siguientes restricciones funcionales y estructurales:
Límites estructurales y de etapas
Etapa raíz: Solo se permite una etapa raíz por búsqueda.
Etapas con nombre: Se admite un máximo de cuatro etapas con nombre.
Referencia de etapas: Una etapa solo puede hacer referencia a etapas definidas lógicamente antes de ella en la misma consulta.
Uniones: Se permite un máximo de cuatro uniones que no sean de tablas de datos en todas las etapas.
Requisito de resultado: Cada etapa con nombre (excepto la etapa raíz) debe incluir una sección
matcho una secciónoutcome. La secciónoutcomeno requiere agregación.
Límites de ventanas y compatibilidad
Compatibilidad con funciones: Las consultas de varias etapas son compatibles con Search y Dashboards, pero no con Rules.
Tipos de ventanas: Evita mezclar diferentes tipos de ventanas en una sola búsqueda.
Dependencia de ventana: Una etapa que usa una ventana deslizante o de salto no puede depender de otra etapa que también use una ventana deslizante o de salto.
Tamaño de la ventana deslizante: Si bien las ventanas deslizantes en diferentes etapas pueden variar en tamaño, la diferencia de tamaño debe ser inferior a 720x.
Ejemplo: Diferencia de agregación por etapa
No se permite la siguiente configuración de ventana de ejemplo:
stage monthly_stats {
metadata.event_type = "NETWORK_CONNECTION"
$source = principal.hostname
$target = target.ip
$source != ""
$target != ""
$total_bytes = cast.as_int(network.sent_bytes + network.received_bytes)
match:
$source, $target by month
outcome:
$exchanged_bytes = sum($total_bytes)
}
$source = $monthly_stats.source
$target = $monthly_stats.target
match:
$source, $target by minute
Si la etapa monthly_stats agrega datos por mes y la etapa raíz agrega el resultado de monthly_stats por minuto, cada fila de monthly_stats se asigna a 43,200 filas en la etapa raíz (porque hay 43,200 minutos en un mes).
Limitaciones de las etapas y las consultas
Cada etapa individual dentro de una consulta de varias etapas tiene las siguientes restricciones:
La mayoría de las limitaciones que se aplican a una consulta de una sola etapa también se aplican a cada etapa individual:
Requisito de salida: Cada etapa debe generar al menos una variable de coincidencia o resultado (campo de etapa).
Ventana en la unión: El tamaño máximo de la ventana (salto, rotación o deslizamiento) que se usa en una unión es de 2 días.
Cantidad máxima de variables de resultado:
20 para los clientes que no habilitaron un límite mayor de la variable de resultado
50 para los clientes que habilitaron un límite mayor de variables de resultado
Cantidad máxima de elementos en una variable de resultado con valores de array.
Las consultas de varias etapas están sujetas a las mismas limitaciones que las consultas de estadísticas:
Consultas de estadísticas: 120 QPH (API y IU)
Vistas de búsqueda de Google SecOps: 100 vistas por minuto
Las uniones de varias etapas son compatibles con la interfaz de usuario y la API de
EventService.UDMSearch, pero no con la API deSearchService.UDMSearch. Las consultas de varias etapas sin uniones también se admiten en la interfaz de usuario.
Limitaciones globales y de eventos
Cantidad máxima de eventos:
Las consultas de varias etapas están estrictamente limitadas en la cantidad de eventos que pueden procesar de forma simultánea:
Eventos del UDM: Se permite un máximo de 2 eventos del UDM.
Eventos del gráfico de contexto de entidades (ECG): Se permite un máximo de un evento del ECG.
Limitaciones de las búsquedas globales:
Estos límites son restricciones en toda la plataforma que controlan la antigüedad y la cantidad de datos que puede devolver una consulta de varias etapas.
En el caso de un intervalo de tiempo de la consulta, el intervalo máximo para una consulta estándar es de 30 días.
El tamaño máximo total del conjunto de resultados es de 10,000 resultados.
Ejemplos de consultas de varias etapas
Los ejemplos de esta sección ayudan a ilustrar cómo puedes crear una consulta de YARA-L completa de varias etapas.
Ejemplo: Buscar conexiones de red inusualmente activas (horas)
Este ejemplo de YARA-L de varias etapas identifica pares de direcciones IP con actividad de red superior a la normal, y se enfoca en los pares que mantienen una actividad alta durante más de tres horas. La consulta incluye dos componentes obligatorios: la etapa con nombre, hourly_stats, y la etapa root.
La etapa hourly_stats busca pares de principal.ip y target.ip con altos niveles de actividad de red.
Esta etapa devuelve un solo valor por hora para los siguientes campos:
Estadísticas de la IP de origen (cadena):
$hourly_stats.src_ipEstadísticas de la IP de destino (cadena):
$hourly_stats.dst_ipEstadísticas para el recuento de eventos (número entero):
$hourly_stats.countDesviación estándar de los bytes recibidos (número de punto flotante):
$hourly_stats.std_recd_bytesPromedio de bytes recibidos (número de punto flotante):
$hourly_stats.avg_recd_bytesHora de inicio del intervalo horario en segundos desde la época de Unix (número entero):
$hourly_stats.window_startHora de finalización del intervalo horario en segundos desde la época de Unix (número entero):
$hourly_stats.window_end
La etapa raíz procesa el resultado de la etapa hourly_stats. Calcula estadísticas para los pares principal.ip y target.ip con actividad que supera el umbral especificado por $hourly_stats. Luego, filtra los pares con más de tres horas de actividad alta.
stage hourly_stats {
metadata.event_type = "NETWORK_CONNECTION"
$src_ip = principal.ip
$dst_ip = target.ip
$src_ip != ""
$dst_ip != ""
match:
$src_ip, $dst_ip by hour
outcome:
$count = count(metadata.id)
$avg_recd_bytes = avg(network.received_bytes)
$std_recd_bytes = stddev(network.received_bytes)
condition:
$avg_recd_bytes > 100 and $std_recd_bytes > 50
}
$src_ip = $hourly_stats.src_ip
$dst_ip = $hourly_stats.dst_ip
$time_bucket_count = strings.concat(timestamp.get_timestamp($hourly_stats.window_start), "|", $hourly_stats.count)
match:
$src_ip, $dst_ip
outcome:
$list = array_distinct($time_bucket_count)
$count = count_distinct($hourly_stats.window_start)
condition:
$count > 3
Si modificas la condición de coincidencia en la etapa raíz de la siguiente manera, puedes introducir una agregación con ventanas por día para la consulta de varias etapas.
match:
$src_ip, $dst_ip by day
Ejemplo: Busca conexiones de red inusualmente activas (con la puntuación Z)
Esta consulta de varias etapas compara la actividad de red promedio diaria con la actividad de hoy usando un cálculo de la puntuación Z (que mide la cantidad de desviaciones estándar con respecto a la media). Esta consulta busca de manera eficaz actividad de red inusualmente alta entre los activos internos y los sistemas externos.
Requisito previo: El período de la consulta debe ser mayor o igual a 2 días y debe incluir el día actual para que la puntuación Z calculada sea efectiva.
Esta consulta de varias etapas incluye la etapa daily_stats y la etapa root, que trabajan en conjunto para calcular la puntuación Z de la actividad de la red:
La etapa
daily_statsrealiza la agregación diaria inicial. Calcula los bytes totales intercambiados cada día para cada par de IP (sourceytarget) y devuelve los siguientes campos de etapa (que corresponden a las columnas de las filas de salida):$daily_stats.source: singular, cadena$daily_stats.target: singular, cadena$daily_stats.exchanged_bytes: Singular, número entero$daily_stats.window_start: Singular, número entero$daily_stats.window_end: Singular, número entero
La etapa raíz agrega el resultado de la etapa
daily_statspara cada par de IP. Calcula el promedio y la desviación estándar de los bytes diarios intercambiados en todo el rango de búsqueda, junto con los bytes intercambiados hoy. Utiliza esos tres valores calculados para determinar la puntuación Z.En el resultado, se enumeran las puntuaciones Z de todos los pares de IP del día, ordenadas de forma descendente.
// Calculate the total bytes exchanged per day by source and target
stage daily_stats {
metadata.event_type = "NETWORK_CONNECTION"
$source = principal.hostname
$target = target.ip
$source != ""
$target != ""
$total_bytes = cast.as_int(network.sent_bytes + network.received_bytes)
match:
$source, $target by day
outcome:
$exchanged_bytes = sum($total_bytes)
}
// Calculate the average per day over the time window and compare with the bytes
exchanged today
$source = $daily_stats.source
$target = $daily_stats.target
$date = timestamp.get_date($daily_stats.window_start)
match:
$source, $target
outcome:
$today_bytes = sum(if($date = timestamp.get_date(timestamp.current_seconds()), $daily_stats.exchanged_bytes, 0))
$average_bytes = window.avg($daily_stats.exchanged_bytes)
$stddev_bytes = window.stddev($daily_stats.exchanged_bytes)
$zscore = ($today_bytes - $average_bytes) / $stddev_bytes
order:
$zscore desc
Cómo exportar variables sin agregar de etapas
Las etapas con nombre pueden incluir una sección outcome sin agregar. Esto significa que las variables definidas dentro de esa sección outcome se generan directamente desde la etapa, lo que permite que las etapas posteriores accedan a ellas como campos de etapa sin necesidad de una agregación agrupada.
Ejemplo: Exporta una variable sin agregar
En este ejemplo, se muestra cómo exportar variables sin agregar. Ten en cuenta la siguiente lógica:
La etapa
top_5_bytes_sentbusca los cinco eventos con la mayor actividad de red.La etapa
top_5_bytes_sentgenera los siguientes campos de etapa que corresponden a las columnas de las filas de salida:$top_5_bytes_sent.bytes_sent: Singular, número entero$top_5_bytes_sent.timestamp_seconds: Singular, número entero
La etapa
rootcalcula las marcas de tiempo más recientes y más tempranas para los cinco eventos con la mayor actividad de red.
stage top_5_bytes_sent {
metadata.event_type = "NETWORK_CONNECTION"
network.sent_bytes > 0
outcome:
$bytes_sent = cast.as_int(network.sent_bytes)
$timestamp_seconds = metadata.event_timestamp.seconds
order:
$bytes_sent desc
limit:
5
}
outcome:
$latest_timestamp = timestamp.get_timestamp(max($top_5_bytes_sent.timestamp_seconds))
$earliest_timestamp = timestamp.get_timestamp(min($top_5_bytes_sent.timestamp_seconds))
Implementa el sistema de ventanas en consultas de varias etapas
Las consultas de varias etapas admiten todos los tipos de ventanas (de salto, deslizantes y continuas) en etapas con nombre. Si una etapa con nombre incluye una ventana, se puede acceder al inicio y al final de la ventana para cada fila de salida con los siguientes campos reservados:
$<stage name>.window_start$<stage name>.window_end
Ejemplo: Ventana de salto
En el siguiente ejemplo, se ilustra cómo podrías usar ventanas de salto en una consulta de varias etapas:
La etapa
hourly_statsbusca pares de IP que tengan una alta actividad de red en la misma hora.hourly_statsgenera los siguientes campos de etapa que corresponden a las columnas de las filas de salida:$hourly_stats.src_ip: singular, cadena$hourly_stats.dst_ip: singular, cadena$hourly_stats.count: Singular, número entero$hourly_stats.std_recd_bytes: Singular, número de punto flotante$hourly_stats.avg_recd_bytes: Singular, número de punto flotante$hourly_stats.window_start: Singular, número entero$hourly_stats.window_end: Singular, número entero
La etapa raíz filtra los pares de IP con más de 3 horas de actividad alta. Las horas podrían superponerse debido al uso de una ventana de salto en la etapa
hourly_stats.
stage hourly_stats {
metadata.event_type = "NETWORK_CONNECTION"
$src_ip = principal.ip
$dst_ip = target.ip
$src_ip != ""
$dst_ip != ""
match:
$src_ip, $dst_ip over 1h
outcome:
$count = count(metadata.id)
$avg_recd_bytes = avg(network.received_bytes)
$std_recd_bytes = stddev(network.received_bytes)
condition:
$avg_recd_bytes > 100 and $std_recd_bytes > 50
}
$src_ip = $hourly_stats.src_ip
$dst_ip = $hourly_stats.dst_ip
$time_bucket_count = strings.concat(timestamp.get_timestamp($hourly_stats.window_start), "|", $hourly_stats.count)
match:
$src_ip, $dst_ip
outcome:
$list = array_distinct($time_bucket_count)
$count = count_distinct($hourly_stats.window_start)
condition:
$count > 3
Problemas conocidos
Te recomendamos que revises las siguientes limitaciones y soluciones alternativas recomendadas cuando implementes consultas de varias etapas:
Todas las consultas de varias etapas se comportan como consultas de búsqueda de estadísticas (el resultado consta de estadísticas agregadas en lugar de eventos sin agregar o filas de tablas de datos).
El rendimiento de las combinaciones con eventos de UDM y de entidades en un lado puede ser bajo debido al tamaño de ese conjunto de datos. Te recomendamos que filtres los eventos de UDM y de entidades del lado de la unión tanto como sea posible (por ejemplo, filtra por tipo de evento).
Para obtener orientación general sobre las prácticas recomendadas, consulta Prácticas recomendadas de Yara-L y, para obtener información específica sobre las uniones, consulta Prácticas recomendadas.
¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.