Problemas conocidos de YARA-L 2.0
Este documento está destinado a los ingenieros de detección que desean depurar la lógica de las reglas y optimizar la ejecución de YARA-L 2.0. En él, se explica cómo controlar los comportamientos no estándar del motor, como la anulación de la anidación de campos, la expansión del producto cartesiano en las agregaciones y la coherencia eventual del enriquecimiento. Si sigues estos métodos, puedes evitar errores lógicos que generen valores de resultados inflados o detecciones perdidas.
YARA-L 2.0 usa un modelo de ejecución específico en el que los campos repetidos se expanden en filas de eventos individuales durante la evaluación. Debido a que esta transformación ocurre a nivel del motor, hacer referencia a varios campos repetidos o realizar operaciones aritméticas en tipos de UDM sin signo requiere soluciones alternativas de sintaxis específicas para evitar errores del compilador o conjuntos de resultados incorrectos. En este documento, se describen esas restricciones técnicas y los patrones lógicos necesarios para resolverlas.
Antes de comenzar
Asegúrate de que tu cuenta tenga los siguientes derechos técnicos antes de probar o modificar las reglas de YARA-L 2.0:
Roles de IAM obligatorios
roles/chronicle.viewer(lector de Security Operations): Para ver las reglas existentes y los metadatos de detecciónroles/chronicle.editor(editor de Security Operations): Para modificar la lógica de las reglas y guardar los cambios
Permisos necesarios
chronicle.rules.runTest: Es necesario para ejecutar la función Ejecutar prueba en datos históricos.chronicle.detections.get: Para inspeccionar el resultado de los eventos no anidados en el panel de detección
Terminología clave
- UDM (modelo de datos unificado): Es el esquema normalizado que se usa para estructurar toda la telemetría de seguridad ingerida en la plataforma.
- Anulación de la anidación: Es la expansión a nivel del motor de un solo evento de UDM que contiene un campo repetido (array) en varias filas. Cada fila representa un elemento único del array, lo que puede generar la multiplicación de filas durante la evaluación de reglas.
- T₀ (ejecución inicial): Es la primera ejecución de una regla en la telemetría entrante. Esto ocurre durante la fase de "transmisión", a menudo antes de que se finalicen los procesos de enriquecimiento en segundo plano (como las regularizaciones de GeoIP o ASN).
Agregaciones de resultados con anulación de la anidación de campos repetidos
Cuando una regla hace referencia a un campo repetido en una variable de evento con varios elementos, cada elemento se divide en una fila de evento separada.
Por ejemplo, las dos direcciones IP del campo repetido target.ip en el evento $e se dividen en dos instancias de $e, cada una con un valor target.ip diferente.
rule outbound_ip_per_app {
meta:
events:
$e.principal.application = $app
match:
$app over 10m
outcome:
$outbound_ip_count = count($e.target.ip) // yields 2.
condition:
$e
}
Registros de eventos: Antes y después de la anulación de la anidación
En las tablas de esta sección, se muestra cómo un solo evento que contiene un array de direcciones IP se transforma en dos registros distintos.
Antes de la anulación de la anidación
En la siguiente tabla, se muestra el registro de eventos antes de anular la anidación del campo repetido:
| metadata.id | principal.application | target.ip |
|---|---|---|
aaaaaaaaa |
Google SecOps |
[192.0.2.20, 192.0.2.28] |
Después de la anulación de la anidación
En la siguiente tabla, se muestra el registro de eventos después de anular la anidación del campo repetido:
| metadata.id | principal.application | target.ip |
|---|---|---|
aaaaaaaaa |
Google SecOps |
192.0.2.20 |
aaaaaaaaa |
Google SecOps |
192.0.2.28 |
Campos repetidos anidados (producto cartesiano)
Cuando una regla hace referencia a un campo repetido anidado dentro de otro, como security_results.action, la anulación de la anidación ocurre en ambos niveles (superior y secundario) de forma simultánea. Esto genera un producto cartesiano de todos los elementos.
En el siguiente ejemplo, un evento $e con dos valores repetidos en security_results y dos valores repetidos
en security_results.actions se anulan en cuatro instancias.
rule security_action_per_app {
meta:
events:
$e.principal.application = $app
match:
$app over 10m
outcome:
$security_action_count = count($e.security_results.actions) // yields 4.
condition:
$e
}
Registro de eventos antes de la anulación de la anidación anidada
El registro original almacena las acciones dentro de una estructura de array anidada.
| metadata.id | principal.application | security_results |
|---|---|---|
aaaaaaaaa |
Google SecOps |
[ { actions: [ ALLOW, FAIL ] }, { actions: [ CHALLENGE, BLOCK ] } ] |
Registros de eventos después de la anulación de la anidación anidada
Después de la expansión, cada acción única se convierte en su propia fila, lo que puede generar recuentos inesperados en agregaciones no distintas.
| metadata.id | principal.application | security_results.actions |
|---|---|---|
aaaaaaaaa |
Google SecOps |
PERMITIR |
aaaaaaaaa |
Google SecOps |
REPROBADA |
aaaaaaaaa |
Google SecOps |
DESAFÍO |
aaaaaaaaa |
Google SecOps |
BLOQUEAR |
Impacto en campos no relacionados
Este comportamiento de anulación de la anidación en la evaluación de reglas puede producir agregaciones de resultados inesperadas cuando la regla hace referencia a uno o más campos repetidos con un campo superior que también es un campo repetido. Las agregaciones no distintas, como sum(), array() y count(), no pueden tener en cuenta los valores duplicados en otros campos del mismo evento producido por el comportamiento de anulación de la anidación.
En el siguiente ejemplo, el evento $e tiene un solo nombre de host (google.com), pero el resultado (hostnames) se agrega en cuatro instancias no anidadas del mismo evento $e, cada una con un valor principal.hostname duplicado. Este resultado genera cuatro nombres de host (en lugar de uno) debido a la anulación de la anidación de valores repetidos en security_results.actions.
rule security_action_per_app {
meta:
events:
$e.principal.application = $app
match:
$app over 10m
outcome:
$hostnames = array($e.principal.hostname) // yields 4.
$security_action_count = count($e.security_results.action) // yields 4.
condition:
$e
}
Registro de eventos antes de la anulación de la anidación con campos no relacionados
El nombre de host es un valor único, pero se encuentra junto a los resultados de seguridad repetidos.
| metadata.id | principal.application | principal.hostname | security_results |
|---|---|---|---|
aaaaaaaaa |
Google SecOps |
google.com |
[ { action: [ ALLOW, FAIL ] }, { action: [ CHALLENGE, BLOCK ] } ] |
Registro de eventos después de la anulación de la anidación con campos no relacionados
El nombre de host ahora está duplicado en cuatro filas, lo que hace que la función array() lo recupere cuatro veces.
| metadata.id | principal.application | principal.hostname | security_results.action |
|---|---|---|---|
aaaaaaaaa |
Google SecOps |
google.com |
PERMITIR |
aaaaaaaaa |
Google SecOps |
google.com |
REPROBADA |
aaaaaaaaa |
Google SecOps |
google.com |
DESAFÍO |
aaaaaaaaa |
Google SecOps |
google.com |
BLOQUEAR |
Solución alternativa para el comportamiento de anulación de la anidación
Para asegurarte de que los valores de los resultados sean precisos cuando se produce la anulación de la anidación, usa la versión distinta de la agregación seleccionada. Las siguientes funciones ignoran las filas duplicadas creadas por la anulación de la anidación:
max()min()array_distinct()count_distinct()
Agregaciones de resultados con varias variables de evento
Si una regla contiene varias variables de evento, hay un elemento separado en la agregación para cada combinación de eventos que se incluye en la detección. Por ejemplo, si la siguiente regla de ejemplo se ejecuta en los eventos enumerados:
events:
$e1.field = $e2.field
$e2.somefield = $ph
match:
$ph over 1h
outcome:
$some_outcome = sum(if($e1.otherfield = "value", 1, 0))
condition:
$e1 and $e2
event1:
// UDM event 1
field="a"
somefield="d"
event2:
// UDM event 2
field="b"
somefield="d"
event3:
// UDM event 3
field="c"
somefield="d"
La suma se calcula en cada combinación de eventos, lo que te permite usar ambas variables de evento en los cálculos de valores de resultados. Los siguientes elementos se usan en el cálculo:
1: $e1 = event1, $e2 = event2
2: $e1 = event1, $e2 = event3
3: $e1 = event2, $e2 = event1
4: $e1 = event2, $e2 = event3
5: $e1 = event3, $e2 = event1
5: $e1 = event3, $e2 = event2
Esto genera una suma máxima potencial de 6, aunque $e2 solo puede corresponder a 3 eventos distintos.
Esto afecta la suma, el recuento y el array. Para el recuento y el array, usar count_distinct o array_distinct puede resolver el problema, pero no hay una solución alternativa para la suma.
Paréntesis al comienzo de una expresión
No se admite comenzar una expresión con paréntesis, lo que activa un error de análisis en el editor de reglas.
Sintaxis no válida
parsing: error with token: ")"
invalid operator in events predicate
En el siguiente ejemplo, se genera este tipo de error:
($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600 > 1
Variaciones de sintaxis válidas
Las siguientes variaciones de sintaxis muestran el mismo resultado, pero con una sintaxis válida:
$event.metadata.ingested_timestamp.seconds / 3600 -
$event.metadata.event_timestamp.seconds / 3600 > 1
1 / 3600 * ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) > 1
1 < ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600
El array de índice en el resultado requiere agregación
No se permite indexar directamente un array dentro de la sección outcome para campos repetidos. Requiere una variable de marcador de posición temporal.
outcome:
$principal_user_dept = $suspicious.principal.user.department[0]
Solución alternativa
Captura el índice de array específico en una variable de marcador de posición dentro de la sección events y, luego, haz referencia a ese marcador de posición en tu resultado.
events:
$principal_user_dept = $suspicious.principal.user.department[0]
outcome:
$principal_user_department = $principal_user_dept
Condición OR con no existencia
Si aplicas una condición OR entre dos variables de evento separadas y si la regla coincide con la no existencia, la regla se compila correctamente, pero puede producir detecciones de falsos positivos.
Por ejemplo, la siguiente sintaxis de regla puede coincidir con eventos que tienen $event_a.field = "something", aunque no debería hacerlo:
events:
not ($event_a.field = "something" **or** $event_b.field = "something")
condition:
$event_a and #event_b >= 0
Solución alternativa
Separa las verificaciones de no existencia en bloques individuales para cada variable para mantener la integridad lógica.
events:
not ($event_a.field = "something")
not ($event_b.field = "something")
condition:
$event_a and #event_b >= 0
Aritmética con campos de eventos sin signo
Si intentas usar una constante de número entero en una operación aritmética con un campo de UDM cuyo tipo es un número entero sin signo, obtendrás un error. Por ejemplo:
events:
$total_bytes = $e.network.received_bytes * 2
Las constantes de números enteros estándar usan números enteros con signo de forma predeterminada, que son incompatibles con los campos de UDM definidos como números enteros sin signo, como network.received_bytes.
Solución alternativa
Puedes omitir este error si fuerzas a la constante de número entero a comportarse como un número de punto flotante a través de una operación de división.
events:
$total_bytes = $e.network.received_bytes * (2/1)
Enriquecimiento de GeoIP y coherencia eventual
El sistema prioriza la velocidad por sobre la precisión inmediata en las etapas iniciales de enriquecimiento (transmisión y sensible a la latencia), lo que puede generar la falta de datos y posibles falsos positivos. El sistema continúa enriqueciendo los datos en segundo plano, pero es posible que los datos no estén disponibles cuando se ejecute la regla. Esto es parte del proceso normal de coherencia eventual.
Para evitar falsos positivos causados por el retraso del enriquecimiento, verifica de forma explícita que el campo no esté vacío antes de evaluar su valor.
Por ejemplo, considera este evento de regla:
$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"
La regla se basa en el hecho de que el evento debe tener $e.principal.ip_geo_artifact.network.asn = "16509" Y $e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom", que son campos enriquecidos. Si el enriquecimiento no se completa a tiempo, la regla producirá un falso positivo.
Para evitar esto, una mejor verificación para esta regla sería la siguiente:
$e.principal.ip_geo_artifact.network.asn != "" AND
$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region != "" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"
Esta regla elimina la posibilidad de que el evento se active con IPs con el ASN 16509, pero ubicadas fuera del Reino Unido. Esto mejora la precisión general de la regla.
Obtén más información para solucionar problemas relacionados con el retraso del enriquecimiento.
Soluciona problemas
En esta sección, se describen las expectativas de rendimiento y se proporcionan correcciones de autoservicio para problemas comunes en los que el comportamiento de la detección en vivo difiere de los resultados de las pruebas.
Eventos con fechas futuras
Las reglas de varios eventos están diseñadas para procesar eventos en orden cronológico en relación con la ingesta. Si especificas y activas una regla de varios eventos, no se crean detecciones para eventos con marcas de tiempo futuras, por ejemplo, cuando event.timestamp tiene una fecha y hora establecidas después de ingest.timestamp.
Retraso del enriquecimiento
Google SecOps prioriza la velocidad de ingesta para exponer las alertas iniciales lo más rápido posible. Sin embargo, los procesos de enriquecimiento en segundo plano, como la resolución de metadatos GeoIP, ASN o UDM, siguen un modelo de coherencia eventual.
Ejecución inicial (T₀)
El motor en vivo puede evaluar una regla antes de que se complete el enriquecimiento en segundo plano. Según si tu lógica se basa en campos enriquecidos para detecciones o exclusiones, esto puede generar las siguientes discrepancias temporales:
Falsos negativos (retraso de detección): Este es un resultado común. Si una regla depende de un campo enriquecido para activarse (por ejemplo,
target.user.department == "Finance") y ese campo esnull, la regla no coincide durante la ejecución inicial.Falsos positivos (exclusión perdida): Si tu regla usa campos enriquecidos para filtrar la actividad conocida como correcta (por ejemplo,
NOT target.ip_geo_country == "US"), la regla puede activar un falso positivo porque los datos de "exclusión" aún no se aplicaron.
Ejecuciones de regularización
Estas ejecuciones en segundo plano vuelven a evaluar los datos después de una demora (por ejemplo, 45 minutos o 30 horas). Esto "regulariza" los estados de detección de la siguiente manera:
Detecciones tardías: Los eventos que fueron "falsos negativos" en T₀ ahora producen una detección una vez que se finaliza el enriquecimiento.
Corrección: Los falsos positivos de T₀ permanecen en el sistema, pero los datos completamente enriquecidos son visibles en el visor de UDM para la clasificación manual.
Discrepancia de la prueba de ejecución
La herramienta Ejecutar prueba opera con datos históricos que ya se reconciliaron. Debido a que los datos están completamente enriquecidos cuando ejecutas una prueba manual, puedes ver los resultados de la "regularización" de inmediato. Esto significa que no verás los falsos negativos de T₀ ni los falsos positivos basados en exclusiones que ocurrieron durante la ejecución inicial en vivo.
Corrección de errores
Usa la siguiente tabla para resolver las discrepancias entre las alertas en vivo y los resultados de las pruebas.
| Problema | Descripción | Corrección práctica |
|---|---|---|
| Falla de exclusión | Se activa una regla a pesar de una exclusión (por ejemplo, != "ASN_123") porque el campo era nulo durante la ejecución inicial. |
Agrega una verificación no nula a la sección de eventos para asegurarte de que los datos se enriquezcan antes de la evaluación, por ejemplo:$e.principal.ip_geo_artifact.network.asn != ""
|
| Coincidencia en vivo en comparación con la prueba | Las reglas en vivo activan alertas, pero la prueba de ejecución en los mismos datos muestra "No Results". |
Agrega $e.field != "" que verifica todos los campos enriquecidos (GeoIP, ASN, File Path) para sincronizar el comportamiento en vivo y el histórico. |
| Faltan metadatos | Las detecciones aparecen en el panel con campos GeoIP o File Path vacíos. |
Esto es normal para las ejecuciones T0. Para corregir este problema, incluye una verificación field != "" o aumenta el desplazamiento de la primera ejecución en tu programación de ejecución para permitir más tiempo para la ingesta.
|
Validación y prueba
Para verificar que una regla controle correctamente el enriquecimiento retrasado, haz lo siguiente:
Identifica el retraso: Busca una detección que creas que es un falso positivo. En la columna Tipo de detección, busca el ícono
<span class="material-icons">lightbulb</span>. Las alertas sin este ícono son de la ejecución inicial, en la que el retraso del enriquecimiento es más común.Actualiza la lógica de la regla: Agrega una verificación
field != ""para todos los datos enriquecidos que se usan en tu lógica.
Ejemplo (ruta de acceso a archivos):
$e.target.process.parent_process.file.full_path != ""Prueba y verifica:
- Usa la función Ejecutar prueba para asegurarte de que tu lógica aún coincida con los datos históricos deseados.
- Verifica que la regla ahora solo se active (o se excluya correctamente) durante las ejecuciones de regularización una vez que se propaguen los campos de enriquecimiento.
Para obtener más detalles, consulta Administra tu programación de ejecución de reglas y Configura programaciones personalizadas para las reglas.
¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.