Correlaciona datos con uniones externas
En este documento, se describen las uniones externas (unión izquierda y unión derecha). Las operaciones de unión se usan para correlacionar y combinar datos de varias fuentes según los valores de campo comunes. Si combinas eventos y entidades de seguridad relacionados en una sola vista integral, puedes proporcionar una detección y una investigación de amenazas eficaces.
A diferencia de las uniones (internas) estándar, que requieren entradas coincidentes en ambas fuentes de datos, una unión externa recupera todos los registros de un lado de la unión, incluso
si no hay entradas coincidentes en el otro. Los campos no coincidentes del otro
lado suelen completarse con null. Esto evita que pierdas datos que no tienen una coincidencia.
Cómo funcionan las uniones externas
El concepto de uniones externas en YARA-L 2.0 es idéntico a las uniones externas de SQL estándar:
La unión externa izquierda conserva todos los registros del lado izquierdo de la unión.
La unión externa derecha conserva todos los registros del lado derecho de la unión.
La sintaxis de unión externa (unión izquierda y unión derecha) es compatible con todas
las consultas, con y sin una condición match. El comportamiento fundamental de
una unión externa es el mismo en la búsqueda, los paneles y las reglas de detección,
aunque la sintaxis difiere según el contexto:
Búsqueda y paneles: Usa las palabras clave explícitas
left joinoright joinen la secciónevents.Reglas de detección: Define la relación de unión con un signo igual (
=) en la seccióneventsy especifica una condición sin límites en la seccióncondition(por ejemplo,#data_table >= 0para una unión externa izquierda o#data_table = 0para una exclusión antiunión).
Comprende la unión externa izquierda
Una unión externa izquierda (o unión izquierda) conserva todos los registros de la fuente de datos
en el lado izquierdo (conservado) de la unión, ya sea que uses la palabra clave left join
en la búsqueda o una condición sin límites
(#data_table >= 0) en una regla de detección.
Si un registro del lado izquierdo no tiene coincidencia en la tabla de eventos o datos de la derecha, los campos del lado derecho se devuelven como
null.Implicación del marcador de posición: Cualquier variable de marcador de posición que se use en la sección
matchdebe hacer referencia a un campo del evento de la izquierda para garantizar una agregación de datos precisa en todo el conjunto de resultados.
Ejemplo de unión izquierda de evento a evento
En el siguiente ejemplo, se muestra una unión externa izquierda para correlacionar los eventos de acceso de los usuarios
con los eventos de conexión de red posteriores que ocurren en el mismo host.
La unión izquierda garantiza que todos los eventos USER_LOGIN se conserven en el conjunto de resultados. Si se encuentra un evento NETWORK_CONNECTION ($e2) coincidente, se unen sus datos.
Si no se encuentra ninguna coincidencia, los campos de $e2 serán null.
$e1.metadata.event_type = "USER_LOGIN"
$e2.metadata.event_type = "NETWORK_CONNECTION"
left join $e1.principal.hostname = $e2.principal.hostname
Define el evento de salida
En el siguiente ejemplo de consulta, se define el lado izquierdo de la unión ($e1), que es
el conjunto de eventos que se conserva en el resultado final:
$e1.metadata.event_type = "USER_LOGIN"
En la siguiente tabla, se representa el resultado de la consulta, que identifica el conjunto inicial de eventos de acceso de los usuarios:
| Tipo de evento | Nombre de host principal | Dirección IP |
|---|---|---|
USER_LOGIN
|
workstation-01
|
192.168.1.101
|
USER_LOGIN
|
laptop-hr-02
|
192.168.1.102
|
USER_LOGIN
|
server-db-03
|
10.0.0.50
|
USER_LOGIN
|
kiosk-4
|
192.168.1.104
|
Define el evento correcto
En el siguiente ejemplo de consulta, se define el lado derecho de la unión ($e2), que
es el conjunto de eventos que se compara con los eventos de la izquierda:
$e2.metadata.event_type = "NETWORK_CONNECTION"
En la siguiente tabla, se representa el conjunto de eventos de conexión de red disponibles para la coincidencia:
| Tipo de evento | Nombre de host principal | Dirección IP |
|---|---|---|
NETWORK_CONNECTION
|
workstation-01
|
192.168.1.101
|
NETWORK_CONNECTION
|
laptop-hr-02
|
192.168.1.101
|
NETWORK_CONNECTION
|
kiosk-4
|
203.0.113.3
|
Únete a los eventos
con una sección de coincidencias
En el siguiente ejemplo, se muestra una consulta de coincidencia con una unión externa izquierda en
el campo principal.hostname:
$e1.metadata.event_type = "USER_LOGIN"
$e2.metadata.event_type = "NETWORK_CONNECTION"
left join $e1.principal.hostname = $e2.principal.hostname
$host = $e1.principal.hostname
match:
$host over 5m
La unión externa izquierda garantiza que cada evento
USER_LOGIN($e1) se incluya en el conjunto de resultados final.Al marcador de posición $host se le asigna el valor de
$e1.principal.hostname. La unión externa izquierda garantiza la presencia del evento$e1, lo que asegura que la variable $host siempre se complete para la agregación.La regla agrega los resultados por host para un período de 5 minutos.
Resultado de la unión
Los datos resultantes muestran la combinación de los dos eventos. Se conservan todos los registros
de la tabla izquierda ($e1) y los campos de la tabla derecha ($e2)
se establecen en null cuando no se encuentra un nombre de host coincidente (por ejemplo, para
server-db-03).
Tipo de evento ($e1)
|
Nombre de host principal ($host)
|
Dirección IP ($e1)
|
Tipo de evento ($e2)
|
Dirección IP ($e2)
|
Estado de coincidencia |
|---|---|---|---|---|---|
USER_LOGIN
|
workstation-01
|
192.168.1.101
|
NETWORK_CONNECTION
|
192.168.1.101
|
Se encontró una coincidencia |
USER_LOGIN
|
laptop-hr-02
|
192.168.1.102
|
NETWORK_CONNECTION
|
192.168.1.101
|
Se encontró una coincidencia |
USER_LOGIN
|
server-db-03
|
10.0.0.50
|
null
|
null
|
No hay coincidencias |
USER_LOGIN
|
kiosk-4
|
192.168.1.104
|
NETWORK_CONNECTION
|
203.0.113.3
|
Se encontró una coincidencia |
Ejemplos de consultas de unión izquierda
En esta sección, se proporcionan ejemplos de consultas de unión izquierda.
Uniones con una condición de coincidencia
Entidad de evento
$e1.metadata.event_type = "NETWORK_CONNECTION" $g1.graph.metadata.entity_type = "ASSET" left join $e1.principal.asset.hostname = $g1.graph.entity.asset.hostname $host = $e1.principal.asset.hostname match: $host over 5mEvent-datatable
$host = $e1.principal.hostname left join $e1.principal.hostname = %all_dt_column_types.hostname match: $host by 5m
Uniones sin una condición de coincidencia
Event-event
$e1.metadata.event_type = "USER_LOGIN" $e1.principal.ip = "114.241.96.87" $e2.metadata.event_type = "NETWORK_CONNECTION" left join $e1.principal.hostname = $e2.principal.hostnameEntidad de evento
$e1.metadata.event_type = "NETWORK_CONNECTION" $g1.graph.metadata.entity_type = "ASSET" left join $e1.principal.asset.hostname = $g1.graph.entity.asset.hostname $host = $e1.principal.asset.hostnameEvent-datatable
$host = $e1.principal.hostname left join $e1.principal.hostname = %all_dt_column_types.hostname
Uniones izquierdas en las reglas de detección
En las reglas de detección, no usas la palabra clave left join en la sección
events. En su lugar, vinculas un evento de UDM a una
tabla de datos o a un evento secundario en
la sección events con igualdad (=) y controlas el comportamiento de unión en la
sección condition:
| Tipo de unión | Sección events |
Sección condition |
Comportamiento en eventos no coincidentes |
|---|---|---|---|
| Unión interna | $key = %data_table.key |
$e and #data_table > 0 |
Los eventos que no coinciden se descartan del flujo de detección. |
| Unión externa izquierda (enriquecimiento) | $key = %data_table.key |
$e and #data_table >= 0 |
Se conservan todos los eventos de $e; los campos de la tabla de datos que no coinciden son null. |
| Anti-join (exclusión) | $key = %data_table.key |
$e and #data_table = 0 |
Activa una alerta solo cuando la clave del evento no existe en la tabla de datos. |
Ejemplo de unión izquierda de evento a tabla de datos en una regla
En el siguiente ejemplo, se usa una tabla de datos llamada corporate_asset_directory para
enriquecer los eventos con metadatos geográficos y de importancia de los recursos sin descartar
eventos de hosts no administrados.
Define la tabla de datos
La tabla de datos corporate_asset_directory contiene las siguientes filas, con
hostname como columna clave:
hostname (clave) |
country_code |
country_name |
asset_tier |
owner_dept |
risk_score |
|---|---|---|---|---|---|
ES01-W10 |
ES |
Spain |
TIER_3_WORKSTATION |
Finance |
20 |
CH02-SRV |
CH |
Switzerland |
TIER_1_CRITICAL |
Engineering |
80 |
US03-LAP |
US |
United States |
TIER_2_PRODUCTION |
Executive |
50 |
Compara las condiciones de INNER JOIN y LEFT OUTER JOIN
Unión interna (
#corporate_asset_directory > 0): Si se requiere que el recuento de tablas de datos sea mayor que0, se realiza una unión interna. Si un evento se origina en un host no administrado que no aparece encorporate_asset_directory(por ejemplo,unmanaged-byod-09), el evento se filtra y no se genera ninguna detección:rule inner_join_drops_unmatched_events { meta: author = "Google SecOps" description = "Inner join example: drops events whose hostname is not in the data table." events: $e.principal.hostname != "" $hostname = $e.principal.hostname // Direct inner join against data table $hostname = %corporate_asset_directory.hostname match: $hostname over 1h outcome: $country = array_distinct(%corporate_asset_directory.country_code) $asset_tier = array_distinct(%corporate_asset_directory.asset_tier) $risk_score = max(%corporate_asset_directory.risk_score) condition: $e and #corporate_asset_directory > 0 }Unión externa izquierda (
#corporate_asset_directory >= 0): El uso de la condición sin límites#corporate_asset_directory >= 0realiza una unión externa izquierda. Todos los eventos de$ese conservan, incluso cuando el nombre de host no coincide con una fila decorporate_asset_directory.Cuando un evento no coincide con una fila de la tabla de datos, las referencias a
%corporate_asset_directory.columnse evalúan comonull. En la secciónoutcome, usastrings.coalescepara las columnas de cadena y las expresiones condicionalesifpara las columnas numéricas con el objetivo de asignar valores de resguardo predeterminados:rule left_outer_join_enrichment { meta: author = "Google SecOps" description = "Left outer join using #dt >= 0: preserves all events and populates enrichment fields." events: $e.principal.hostname != "" $hostname = $e.principal.hostname // Outer join equality binding $hostname = %corporate_asset_directory.hostname match: $hostname over 1h outcome: $country = array_distinct(strings.coalesce(%corporate_asset_directory.country_code, "UNKNOWN")) $asset_tier = array_distinct(strings.coalesce(%corporate_asset_directory.asset_tier, "UNMANAGED")) $risk_score = max(if(%corporate_asset_directory.risk_score > 0, %corporate_asset_directory.risk_score, 0)) condition: $e and #corporate_asset_directory >= 0 }
Resultado de la unión de reglas
En la siguiente tabla, se comparan los valores de resultado para los hosts coincidentes y
no coincidentes cuando se usa #corporate_asset_directory >= 0:
Nombre de host principal ($hostname) |
Estado de coincidencia de la tabla de datos | $country |
$asset_tier |
$risk_score |
|---|---|---|---|---|
CH02-SRV |
Se encontró una coincidencia | ["CH"] |
["TIER_1_CRITICAL"] |
80 |
ES01-W10 |
Se encontró una coincidencia | ["ES"] |
["TIER_3_WORKSTATION"] |
20 |
unmanaged-byod-09 |
No hay coincidencias (null se reemplazó por los valores predeterminados) |
["UNKNOWN"] |
["UNMANAGED"] |
0 |
Ejemplos de Left anti-join (exclusión) en reglas
Puedes usar una unión externa izquierda con una condición de recuento cero
(#data_table = 0) para realizar una antiunión izquierda. Este
patrón suprime las detecciones cuando un evento coincide con una tabla de datos de exclusión y
activa una alerta solo cuando no hay coincidencia.
Exclusión de una sola columna (
#authorized_scanners_exclusion = 0): La siguiente regla une$e.principal.hostnamecon una tabla de datosauthorized_scanners_exclusiony se activa solo cuando el host no está presente en la tabla:rule anti_join_scanner_exclusion { meta: author = "Google SecOps" description = "Anti-join exclusion using #dt = 0: triggers only if the host is not in the authorized scanners table." events: $e.principal.hostname != "" $hostname = $e.principal.hostname // Bind join key to data table $hostname = %authorized_scanners_exclusion.hostname match: $hostname over 1h outcome: $total_sent_bytes = sum($e.network.sent_bytes) condition: $e and #authorized_scanners_exclusion = 0 }Como alternativa, puedes contar las filas de la tabla de datos coincidentes en la sección
outcome($scanner_match_count = count(%authorized_scanners_exclusion.hostname)) y evaluar$e and $scanner_match_count = 0en la seccióncondition:rule anti_join_outcome_count { meta: author = "Google SecOps" description = "Anti-join via outcome variable count check: triggers when scanner match count is zero." events: $e.principal.hostname != "" $hostname = $e.principal.hostname $hostname = %authorized_scanners_exclusion.hostname match: $hostname over 1h outcome: $total_sent_bytes = sum($e.network.sent_bytes) $scanner_match_count = count(%authorized_scanners_exclusion.hostname) condition: $e and $scanner_match_count = 0 }Exclusión de tuplas de filas de varias columnas (
#multi_column_admin_exceptions = 0): Para excluir eventos solo cuando una combinación específica de varios campos coincida con la misma fila en una tabla de datos de excepción, vincula cada campo de evento a su columna correspondiente en la seccióneventsy especifica#data_table = 0en la seccióncondition:rule multi_column_tuple_exclusion { meta: author = "Google SecOps" description = "Multi-column row-tuple anti-join: excludes activity matching composite (origin_ip, target_ip, username, action) rows." events: // Bind event fields to match variables $e.principal.ip = $src_ip $e.target.ip = $dst_ip $e.principal.user.userid = $user $e.metadata.product_event_type = $action // Multi-column equality against the same data table row $src_ip = %multi_column_admin_exceptions.origin_ip $dst_ip = %multi_column_admin_exceptions.target_ip $user = %multi_column_admin_exceptions.username $action = %multi_column_admin_exceptions.action match: $src_ip, $dst_ip, $user, $action over 5m outcome: $event_count = count($e.metadata.id) condition: $e and #multi_column_admin_exceptions = 0 }
Unión externa derecha
Una unión externa derecha (o unión derecha) conserva todos los registros de la fuente de datos en
el lado derecho de la palabra clave right join.
Si un registro del evento de la derecha no tiene coincidencia en el evento de la izquierda, los campos del evento de la izquierda se devuelven como
null.Implicación del marcador de posición: Cualquier variable de marcador de posición que se use en la sección
matchdebe hacer referencia a un campo del evento correcto para garantizar la agregación precisa de datos en todo el conjunto de resultados.
Ejemplo de unión derecha de evento a evento
En el siguiente ejemplo, se muestra una right outer join para correlacionar los eventos de acceso de los usuarios
con los eventos de conexión de red posteriores que ocurren en el mismo host.
El right join garantiza que todos los eventos NETWORK_CONNECTION se conserven en el
conjunto de resultados. Si se encuentra un evento de USER_LOGIN coincidente, se unen sus datos.
Si no se encuentra ninguna coincidencia, los campos de $e1 serán null.
$e1.metadata.event_type = "USER_LOGIN"
$e2.metadata.event_type = "NETWORK_CONNECTION"
right join $e1.principal.hostname = $e2.principal.hostname
Define el evento de salida
En la siguiente consulta, se define el lado izquierdo de la unión ($e1), que es el conjunto de eventos opcional
en el resultado final:
$e1.metadata.event_type = "USER_LOGIN"
En la siguiente tabla, se representa el resultado de la consulta, que identifica el conjunto inicial de eventos de acceso de los usuarios:
| Tipo de evento | Nombre de host principal | Dirección IP |
|---|---|---|
USER_LOGIN
|
workstation-01
|
192.168.1.101
|
USER_LOGIN
|
laptop-hr-02
|
192.168.1.102
|
USER_LOGIN
|
server-db-03
|
10.0.0.50
|
Define el evento correcto
La siguiente consulta define el lado derecho de la unión ($e2), que es el conjunto de eventos
que se conserva en el resultado final.
$e2.metadata.event_type = "NETWORK_CONNECTION"
En la siguiente tabla, se muestra el conjunto de eventos de conexión de red disponibles para la coincidencia.
| Tipo de evento | Nombre de host principal | Dirección IP |
|---|---|---|
NETWORK_CONNECTION
|
workstation-01
|
192.168.1.101
|
NETWORK_CONNECTION
|
laptop-hr-02
|
192.168.1.101
|
NETWORK_CONNECTION
|
vm-unauth-05
|
203.0.113.3
|
Únete a los eventos
En el siguiente ejemplo, se muestra una consulta de coincidencia con una unión externa derecha en el
campo principal.hostname:
$e1.metadata.event_type = "USER_LOGIN"
$e2.metadata.event_type = "NETWORK_CONNECTION"
right join $e1.principal.hostname = $e2.principal.hostname
$host = $e1.principal.hostname
match:
$host over 5m
La unión externa derecha garantiza que cada evento de
NETWORK_CONNECTION($e2) se incluya en el conjunto de resultados final.Al marcador de posición
$hostse le asigna el valor de$e2.principal.hostname. La unión externa derecha garantiza la presencia del evento$e2, lo que asegura que la variable$hostsiempre se complete para la agregación.La regla agrega los resultados por host para un período de 5 minutos.
Resultado de la unión
El conjunto de datos resultante muestra la combinación de los dos eventos. Se conservan todos los registros de
la tabla derecha ($e2) y los campos de la tabla izquierda ($e1) se establecen
como nulos cuando no se encuentra un nombre de host coincidente (por ejemplo, vm-unauth-05).
Tipo de evento ($e1)
|
Nombre de host principal ($e1)
|
Dirección IP ($e1)
|
Tipo de evento ($e2)
|
Nombre de host principal ($host) | Dirección IP ($e2)
|
Estado de coincidencia |
|---|---|---|---|---|---|---|
USER_LOGIN
|
workstation-01
|
192.168.1.101
|
NETWORK_CONNECTION
|
workstation-01
|
192.168.1.101
|
Se encontró una coincidencia |
USER_LOGIN
|
laptop-hr-02
|
192.168.1.102
|
NETWORK_CONNECTION
|
laptop-hr-02
|
192.168.1.101
|
Se encontró una coincidencia |
null
|
null
|
null
|
NETWORK_CONNECTION
|
vm-unauth-05
|
203.0.113.4
|
No hay coincidencias |
Ejemplos de consultas de unión derecha
En esta sección, se proporcionan ejemplos de consultas de unión derecha.
Uniones con una condición de coincidencia
Event-event
$e1.metadata.event_type = "USER_LOGIN" $e2.metadata.event_type = "NETWORK_CONNECTION" right join $e1.principal.hostname = $e2.principal.hostname $host = $e2.principal.hostname match: $host over 5mEvento de entidad
$e1.metadata.event_type = "NETWORK_CONNECTION" $g1.graph.metadata.entity_type = "ASSET" right join $g1.graph.entity.asset.hostname = $e1.principal.asset.hostname $host = $e1.principal.asset.hostname match: $host over 5mDatatable-event
$host = $e1.principal.hostname right join %all_dt_column_types.hostname = $e1.principal.hostname match: $host by 5m
Uniones sin una condición de coincidencia
Event-event
$e1.metadata.event_type = "USER_LOGIN" $e1.principal.ip = "114.241.96.87" $e2.metadata.event_type = "NETWORK_CONNECTION" right join $e1.principal.hostname = $e2.principal.hostnameEvento de entidad
$e1.metadata.event_type = "NETWORK_CONNECTION" $g1.graph.metadata.entity_type = "ASSET" right join $g1.graph.entity.asset.hostname = $e1.principal.asset.hostname $host = $e1.principal.asset.hostnameDatatable-event
$host = $e1.principal.hostname right join %all_dt_column_types.hostname = $e1.principal.hostname
Limitaciones
Ten en cuenta las siguientes limitaciones cuando crees uniones externas:
No se admite una unión externa completa (unión izquierda y unión derecha juntas).
El período de la consulta para las uniones sin coincidencias se limita a un máximo de 14 días.
No puedes unir directamente dos fuentes contextuales (por ejemplo, una entidad directamente a una tabla de datos).
El evento principal del modelo de datos unificado (UDM) debe ser el lado conservado de la unión externa. La consulta no es válida si el evento principal está en el lado "anulable".
Una unión de evento-entidad debe ser una unión izquierda. Esto conserva correctamente el evento (
$e1).Una unión de entidad-evento debe ser una unión derecha. Esto conserva correctamente el evento (
$e1).
El siguiente ejemplo no es válido porque el evento de UDM (
$e1) está a la izquierda, pero la unión derecha conserva el lado derecho ($g1), lo que infringe la regla de que se debe conservar el evento de UDM:// Invalid query $e1.metadata.event_type = "NETWORK_CONNECTION" $g1.graph.metadata.entity_type = "ASSET" right join $e1.principal.asset.hostname = $g1.graph.entity.asset.hostnameLas palabras clave explícitas
left joinyright joinde la seccióneventsno se admiten en las reglas de detección y solo se admiten en las búsquedas de YARA-L y los paneles. Para realizar una unión externa izquierda o una antiunión en una regla de detección, usa una condición sin límites, como#data_table >= 0o#data_table = 0en la seccióncondition. Para obtener más detalles, consulta Uniones izquierdas en las reglas de detección.
Prácticas recomendadas
Para evitar el rendimiento lento y los tiempos de espera de las consultas en las consultas de unión externa, usa filtros específicos y limitados.
Por ejemplo, una consulta amplia como la siguiente:
$e1.metadata.event_type = "USER_LOGIN"
$e2.metadata.event_type = "NETWORK_CONNECTION"
right join $e1.principal.hostname = $e2.principal.hostname
Se puede optimizar agregando criterios específicos de la siguiente manera:
$e1.metadata.event_type = "USER_LOGIN"
$e1.principal.ip = "121.121.121.121"
$e1.principal.user.userid = "alex"
$e2.metadata.event_type = "NETWORK_CONNECTION"
$e2.src.hostname = "altostrat.com"
$e1.principal.hostname = $e2.principal.hostname
¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.