Correlacionar dados usando junções externas
Neste documento, descrevemos as mesclagens externas (mesclagem à esquerda e à direita). As operações de mesclagem são usadas para correlacionar e combinar dados de várias fontes com base em valores de campo comuns. Ao combinar ocorrências de segurança e entidades relacionadas em uma visualização única e abrangente, é possível fornecer detecção e investigação de ameaças eficazes.
Ao contrário das mesclagens padrão (internas), que exigem entradas correspondentes em ambas as fontes de dados, uma mesclagem externa recupera todos os registros de um lado da mesclagem, mesmo que não haja entradas correspondentes no outro. Os campos não correspondentes do outro
lado geralmente são preenchidos com null. Isso evita que você perca dados que
não têm uma correspondência.
Como as mesclagens externas funcionam
O conceito de junções externas no YARA-L 2.0 é idêntico às junções externas do SQL padrão:
A mesclagem externa à esquerda preserva todos os registros do lado esquerdo da mesclagem.
A mesclagem externa à direita preserva todos os registros do lado direito da mesclagem.
A sintaxe de mesclagem externa (mesclagem à esquerda e à direita) é compatível com todas as
consultas, com e sem uma condição match. O comportamento fundamental de
uma mesclagem externa é o mesmo em pesquisas, painéis e regras de detecção,
embora a sintaxe seja diferente de acordo com o contexto:
Pesquisa e painéis: use as palavras-chave explícitas
left joinouright joinna seçãoevents.Regras de detecção: defina a relação de mesclagem usando um sinal de igual (
=) na seçãoeventse especifique uma condição ilimitada na seçãocondition(por exemplo,#data_table >= 0para uma mesclagem externa à esquerda ou#data_table = 0para uma exclusão de antimesclagem).
Entender a mesclagem externa à esquerda
Uma junção externa esquerda (ou junção esquerda) preserva todos os registros da fonte de dados
no lado esquerdo (preservado) da junção, seja usando a palavra-chave left join
na Pesquisa ou uma condição ilimitada
(#data_table >= 0) em uma regra de detecção.
Se um registro do lado esquerdo não tiver correspondência no evento ou na tabela de dados à direita, os campos do lado direito serão retornados como
null.Implicação do marcador de posição: qualquer variável de marcador de posição usada na seção
matchprecisa referenciar um campo do evento à esquerda para garantir a agregação precisa de dados em todo o conjunto de resultados.
Exemplo de mesclagem à esquerda de evento para evento
O exemplo a seguir demonstra uma mesclagem externa esquerda para correlacionar eventos de login do usuário com eventos de conexão de rede subsequentes que ocorrem no mesmo host.
A mesclagem à esquerda garante que todos os eventos USER_LOGIN sejam preservados no conjunto de resultados. Se um evento NETWORK_CONNECTION ($e2) correspondente for encontrado, os dados dele serão combinados.
Se nenhuma correspondência for encontrada, os campos de $e2 serão null.
$e1.metadata.event_type = "USER_LOGIN"
$e2.metadata.event_type = "NETWORK_CONNECTION"
left join $e1.principal.hostname = $e2.principal.hostname
Definir o evento de saída
O exemplo de consulta a seguir define o lado esquerdo da mesclagem ($e1), que é o conjunto de eventos preservado no resultado final:
$e1.metadata.event_type = "USER_LOGIN"
A tabela a seguir representa o resultado da consulta, identificando o conjunto inicial de eventos de login do usuário:
| Tipo de evento | Nome do host principal | Endereço 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
|
Defina o evento certo
O exemplo de consulta a seguir define o lado direito da mesclagem ($e2), que é o conjunto de eventos que corresponde aos eventos à esquerda:
$e2.metadata.event_type = "NETWORK_CONNECTION"
A tabela a seguir representa o conjunto de eventos de conexão de rede disponíveis para correspondência:
| Tipo de evento | Nome do host principal | Endereço 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
|
Participe dos eventos
com uma seção de correspondência
O exemplo a seguir demonstra uma consulta de correspondência usando uma mesclagem externa esquerda no 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
A mesclagem externa à esquerda garante que todos os eventos
USER_LOGIN($e1) sejam incluídos no conjunto de resultados final.O marcador de posição $host recebe o valor de
$e1.principal.hostname. A mesclagem externa esquerda garante a presença do evento$e1, garantindo que a variável $host seja sempre preenchida para agregação.A regra agrega os resultados por host em uma janela de tempo de 5 minutos.
Resultado da mesclagem
Os dados resultantes mostram a combinação dos dois eventos. Todos os registros
da tabela à esquerda ($e1) são mantidos, e os campos da tabela à direita ($e2)
são definidos como null quando nenhum nome de host correspondente é encontrado (por exemplo, para
server-db-03).
Tipo de evento ($e1)
|
Nome do host principal ($host)
|
Endereço IP ($e1)
|
Tipo de evento ($e2)
|
Endereço IP ($e2)
|
Status da correspondência |
|---|---|---|---|---|---|
USER_LOGIN
|
workstation-01
|
192.168.1.101
|
NETWORK_CONNECTION
|
192.168.1.101
|
Correspondência encontrada |
USER_LOGIN
|
laptop-hr-02
|
192.168.1.102
|
NETWORK_CONNECTION
|
192.168.1.101
|
Correspondência encontrada |
USER_LOGIN
|
server-db-03
|
10.0.0.50
|
null
|
null
|
Nenhuma correspondência |
USER_LOGIN
|
kiosk-4
|
192.168.1.104
|
NETWORK_CONNECTION
|
203.0.113.3
|
Correspondência encontrada |
Exemplos de consultas de mesclagem à esquerda
Nesta seção, mostramos exemplos de consultas de mesclagem à esquerda.
Mesclagens com uma condição de correspondência
Entidade 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
Mesclagens sem uma condição de correspondência
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.hostnameEntidade 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
Mesclagens à esquerda em regras de detecção
Nas regras de detecção, não use a palavra-chave left join na seção
events. Em vez disso, vincule um evento de UDM a uma
tabela de dados ou a um evento secundário na
seção events usando igualdade (=) e controle o comportamento de mesclagem na
seção condition:
| Tipo de mesclagem | Seção events |
Seção condition |
Comportamento em eventos sem correspondência |
|---|---|---|---|
| Inner join | $key = %data_table.key |
$e and #data_table > 0 |
Os eventos sem correspondência são descartados do stream de detecção. |
| Left outer join (enriquecimento) | $key = %data_table.key |
$e and #data_table >= 0 |
Todos os eventos em $e são preservados. Os campos da tabela de dados sem correspondência são null. |
| Anti-join (exclusão) | $key = %data_table.key |
$e and #data_table = 0 |
Aciona um alerta somente quando a chave de evento não existe na tabela de dados. |
Exemplo de mesclagem à esquerda de evento para tabela de dados em uma regra
O exemplo a seguir usa uma tabela de dados chamada corporate_asset_directory para
enriquecer eventos com metadados geográficos e de importância de recursos sem descartar
eventos de hosts não gerenciados.
Definir a tabela de dados
A tabela de dados corporate_asset_directory contém as seguintes linhas, usando
hostname como a coluna de chave:
hostname (chave) |
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 |
Comparar as condições de mesclagem interna e externa à esquerda
Inner join (
#corporate_asset_directory > 0): exigir que a contagem da tabela de dados seja maior que0realiza um inner join. Se um evento se originar de um host não gerenciado que não esteja listado emcorporate_asset_directory(por exemplo,unmanaged-byod-09), o evento será filtrado e nenhuma detecção será gerada: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 }Mesclagem externa à esquerda (
#corporate_asset_directory >= 0): o uso da condição ilimitada#corporate_asset_directory >= 0realiza uma mesclagem externa à esquerda. Todos os eventos em$esão preservados mesmo quando o nome do host não corresponde a uma linha emcorporate_asset_directory.Quando um evento não corresponde a uma linha da tabela de dados, as referências a
%corporate_asset_directory.columnsão avaliadas comonull. Na seçãooutcome, usestrings.coalescepara colunas de string e expressões condicionaisifpara colunas numéricas para atribuir valores de fallback padrão: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 da mesclagem de regras
A tabela a seguir compara os valores de resultado para hosts correspondentes e não correspondentes ao usar #corporate_asset_directory >= 0:
Nome do host principal ($hostname) |
Status de correspondência da tabela de dados | $country |
$asset_tier |
$risk_score |
|---|---|---|---|---|
CH02-SRV |
Correspondência encontrada | ["CH"] |
["TIER_1_CRITICAL"] |
80 |
ES01-W10 |
Correspondência encontrada | ["ES"] |
["TIER_3_WORKSTATION"] |
20 |
unmanaged-byod-09 |
Nenhuma correspondência (null substituído pelos padrões) |
["UNKNOWN"] |
["UNMANAGED"] |
0 |
Exemplos de antijunção à esquerda (exclusão) em regras
É possível usar uma mesclagem externa à esquerda com uma condição de contagem zero
(#data_table = 0) para realizar uma antimesclagem à esquerda. Esse
padrão suprime as detecções quando um evento corresponde a uma tabela de dados de exclusão e
aciona um alerta somente quando não há correspondência.
Exclusão de coluna única (
#authorized_scanners_exclusion = 0): a regra a seguir mescla$e.principal.hostnamecom uma tabela de dadosauthorized_scanners_exclusione é acionada apenas quando o host não está presente na tabela: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, é possível contar as linhas da tabela de dados correspondentes na seção
outcome($scanner_match_count = count(%authorized_scanners_exclusion.hostname)) e avaliar$e and $scanner_match_count = 0na seçãocondition: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 }Exclusão de tupla de linha de várias colunas (
#multi_column_admin_exceptions = 0): para excluir eventos somente quando uma combinação específica de vários campos corresponder à mesma linha em uma tabela de dados de exceção, vincule cada campo de evento à coluna correspondente na seçãoeventse especifique#data_table = 0na seçãocondition: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 }
Right outer join
Uma mesclagem externa à direita (ou mesclagem à direita) preserva todos os registros da fonte de dados no lado direito da palavra-chave right join.
Se um registro do evento à direita não tiver correspondência no evento à esquerda, os campos do evento à esquerda serão retornados como
null.Implicação do marcador de posição:qualquer variável de marcador de posição usada na seção
matchprecisa referenciar um campo do evento correto para garantir a agregação precisa de dados em todo o conjunto de resultados.
Exemplo de junção à direita de evento para evento
O exemplo a seguir demonstra um right outer join para correlacionar eventos de login do usuário
com eventos de conexão de rede subsequentes que ocorrem no mesmo host.
O right join garante que todos os eventos NETWORK_CONNECTION sejam preservados no
conjunto de resultados. Se um evento USER_LOGIN correspondente for encontrado, os dados dele serão mesclados.
Se nenhuma correspondência for encontrada, os campos de $e1 serão null.
$e1.metadata.event_type = "USER_LOGIN"
$e2.metadata.event_type = "NETWORK_CONNECTION"
right join $e1.principal.hostname = $e2.principal.hostname
Definir evento de saída
A consulta a seguir define o lado esquerdo da mesclagem ($e1), que é o conjunto de eventos opcional no resultado final:
$e1.metadata.event_type = "USER_LOGIN"
A tabela a seguir representa o resultado da consulta, identificando o conjunto inicial de eventos de login do usuário:
| Tipo de evento | Nome do host principal | Endereço 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
|
Definir o evento certo
A consulta a seguir define o lado direito da mesclagem ($e2), que é o conjunto de eventos
preservado no resultado final.
$e2.metadata.event_type = "NETWORK_CONNECTION"
A tabela a seguir representa o conjunto de eventos de conexão de rede disponíveis para correspondência.
| Tipo de evento | Nome do host principal | Endereço 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
|
Participe dos eventos
O exemplo a seguir mostra uma consulta de correspondência com uma junção externa direita no 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
A mesclagem externa direita garante que todos os eventos
NETWORK_CONNECTION($e2) sejam incluídos no conjunto de resultados final.O marcador de posição
$hostrecebe o valor de$e2.principal.hostname. A junção externa direita garante a presença do evento$e2, garantindo que a variável$hostseja sempre preenchida para agregação.A regra agrega os resultados por host em uma janela de tempo de 5 minutos.
Resultado da mesclagem
O conjunto de dados resultante mostra a combinação dos dois eventos. Todos os registros da
tabela à direita ($e2) são mantidos, e os campos da tabela à esquerda ($e1) são definidos
como nulos quando nenhum nome de host correspondente é encontrado (por exemplo, vm-unauth-05).
Tipo de evento ($e1)
|
Nome do host principal ($e1)
|
Endereço IP ($e1)
|
Tipo de evento ($e2)
|
Nome do host principal ($host) | Endereço IP ($e2)
|
Status da correspondência |
|---|---|---|---|---|---|---|
USER_LOGIN
|
workstation-01
|
192.168.1.101
|
NETWORK_CONNECTION
|
workstation-01
|
192.168.1.101
|
Correspondência encontrada |
USER_LOGIN
|
laptop-hr-02
|
192.168.1.102
|
NETWORK_CONNECTION
|
laptop-hr-02
|
192.168.1.101
|
Correspondência encontrada |
null
|
null
|
null
|
NETWORK_CONNECTION
|
vm-unauth-05
|
203.0.113.4
|
Nenhuma correspondência |
Exemplos de consultas de mesclagem à direita
Nesta seção, mostramos exemplos de consultas de junção à direita.
Mesclagens com uma condição de correspondência
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 5mEntidade-evento
$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
Mesclagens sem uma condição de correspondência
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.hostnameEntidade-evento
$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
Limitações
Considere as seguintes limitações ao criar mesclagens externas:
Não é possível usar uma mesclagem externa completa (mesclagem à esquerda e à direita juntas).
O período da consulta para junções sem correspondência é limitado a no máximo 14 dias.
Não é possível mesclar diretamente duas fontes contextuais (por exemplo, uma entidade diretamente a uma tabela de dados).
O evento principal do Modelo de dados unificado (UDM) precisa ser o lado preservado da mesclagem externa. A consulta será inválida se o evento principal estiver no lado "anulável".
Uma mesclagem de entidade de evento precisa ser uma mesclagem à esquerda. Isso preserva corretamente o evento (
$e1).Uma mesclagem de entidade-evento precisa ser uma mesclagem à direita. Isso preserva corretamente o evento (
$e1).
O exemplo a seguir é inválido porque o evento de UDM (
$e1) está à esquerda, mas a mesclagem à direita preserva o lado direito ($g1), o que viola a regra de que o evento de UDM precisa ser preservado:// Invalid query $e1.metadata.event_type = "NETWORK_CONNECTION" $g1.graph.metadata.entity_type = "ASSET" right join $e1.principal.asset.hostname = $g1.graph.entity.asset.hostnameAs palavras-chave explícitas
left joineright joinna seçãoeventsnão são compatíveis com as regras de detecção e só são compatíveis com as pesquisas do YARA-L e os painéis. Para realizar uma mesclagem externa à esquerda ou uma antimesclagem em uma regra de detecção, use uma condição ilimitada, como#data_table >= 0ou#data_table = 0, na seçãocondition. Para mais detalhes, consulte Left joins em regras de detecção.
Práticas recomendadas
Para evitar lentidão e tempos limite em consultas de mesclagem externa, use filtros específicos e restritos.
Por exemplo, uma consulta ampla como esta:
$e1.metadata.event_type = "USER_LOGIN"
$e2.metadata.event_type = "NETWORK_CONNECTION"
right join $e1.principal.hostname = $e2.principal.hostname
Pode ser otimizado adicionando critérios específicos da seguinte forma:
$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
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.