Crie consultas de várias fases em YARA-L
Este documento descreve como as consultas de várias fases no YARA-L lhe permitem introduzir o resultado de uma fase de consulta diretamente na entrada de uma fase subsequente. Este processo dá-lhe um maior controlo sobre a transformação de dados do que uma única consulta monolítica.
Integre consultas de várias fases com funcionalidades existentes
As consultas de várias fases funcionam em conjunto com as seguintes funcionalidades existentes no Google Security Operations:
Regras de deteção compostas: as consultas de várias fases complementam as regras de deteção compostas. Ao contrário das regras compostas, as consultas de várias fases que usam a Pesquisa podem devolver resultados em tempo real.
Intervalos de tempo e regras de vários eventos: pode usar consultas de várias fases para detetar anomalias comparando diferentes janelas de tempo nos seus dados. Por exemplo, pode usar as fases de consulta iniciais para estabelecer uma base durante um período prolongado e, em seguida, usar uma fase posterior para avaliar a atividade recente em comparação com essa base. Também pode usar regras de vários eventos para criar um tipo de comparação semelhante.
As consultas de várias fases em YARA-L são suportadas nos painéis de controlo e na pesquisa.
As junções ajudam a correlacionar dados de várias origens para fornecer mais contexto para uma investigação. Ao associar eventos, entidades e outros dados relacionados, pode investigar cenários de ataques complexos. Para mais informações, consulte o artigo Use junções na Pesquisa.
Defina a sintaxe YARA-L de vários passos
Ao configurar uma consulta de várias fases, tenha em atenção o seguinte:
- Limit stage: as consultas de várias fases têm de conter entre 1 e 4 fases com nome, além da fase raiz.
- Sintaxe de ordenação: defina sempre a sintaxe de etapas com nome antes de definir a sintaxe de etapas raiz.
Crie uma consulta YARA-L de várias fases
Para criar uma consulta YARA-L de várias fases, conclua os seguintes passos.
Estrutura e sintaxe das fases
Aceda a Investigação > Pesquisa. Siga estes requisitos estruturais quando definir as fases da consulta:
Sintaxe: use a seguinte sintaxe para atribuir um nome a cada fase e separá-la de outras fases:
stage <stage name> { }
Chavetas: coloque toda a sintaxe de etapas entre chavetas {}.
Order: defina a sintaxe para todas as fases com nome antes de definir a fase raiz.
Referência: cada fase pode fazer referência a fases definidas anteriormente na consulta.
Fase raiz: uma consulta tem de ter uma fase raiz, que é processada após todas as fases com nome.
A fase de exemplo seguinte, daily_stats, recolhe estatísticas de rede diárias:
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)
}
Resultado da fase de acesso
O resultado de uma fase com nome é acessível às fases subsequentes através de campos
de fase. Os campos de etapa correspondem às variáveis match e outcome
da etapa e podem ser usados de forma semelhante aos campos do modelo de dados unificado (UDM).
Use a seguinte sintaxe para aceder a um campo de fase:
$<stage name>.<variable name>
Indicações de tempo da janela de acesso (opcional)
Se uma fase com nome usar uma janela de salto, deslizante ou rotativa, aceda à hora de início e de fim da janela para cada linha de saída através destes campos reservados:
$<stage name>.window_start$<stage name>.window_end
window_start e window_end são campos de números inteiros expressos em segundos desde a época Unix. As janelas em diferentes fases podem variar em tamanho.
Limitações
As consultas de várias fases têm as seguintes restrições funcionais e estruturais:
Limites estruturais e de etapas
Fase raiz: só é permitida uma fase raiz por consulta.
Etapas com nome: é suportado um máximo de quatro etapas com nome.
Referência de etapas: uma etapa só pode fazer referência a etapas definidas logicamente antes dela na mesma consulta.
Junções: é permitido um máximo de quatro junções de tabelas de dados em todas as fases.
Requisito de resultado: cada fase com nome (excluindo a fase raiz) tem de incluir uma secção
matchou uma secçãooutcome. A secçãooutcomenão requer agregação.
Limites de janelas e compatibilidade
Suporte de funcionalidades: as consultas de várias fases são suportadas na Pesquisa e nos Painéis de controlo, mas não são suportadas nas Regras.
Tipos de janelas: evite misturar diferentes tipos de janelas numa única consulta.
Dependência de janelas: uma fase que use uma janela de salto ou deslizante não pode depender de outra fase que também use uma janela de salto ou deslizante.
Tamanho da janela de deslocamento: embora as janelas de deslocamento em diferentes fases possam variar em tamanho, a diferença de tamanho tem de ser inferior a 720x.
Exemplo: diferença de agregação de etapas
A seguinte configuração de janela de exemplo não é permitida:
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
Se a fase monthly_stats agregar dados por mês e a fase raiz agregar o resultado de monthly_stats por minuto, cada linha de monthly_stats é mapeada para 43 200 linhas na fase raiz (porque existem 43 200 minutos num mês).
Limitações de fases e consultas
Cada fase individual numa consulta de várias fases tem as seguintes restrições:
A maioria das limitações que se aplicam a uma consulta de uma única fase também se aplicam a cada fase individual:
Requisito de saída: cada fase tem de gerar, pelo menos, uma variável de correspondência ou de resultado (campo de fase).
Período na junção: a dimensão máxima do período (de salto, de agrupamento ou deslizante) usado numa junção é de 2 dias.
Número máximo de variáveis de resultados:
20 para clientes que não optaram por permitir um limite de variáveis de resultados maior
50 para clientes que optaram por permitir um limite de variáveis de resultados mais elevado
Número máximo de elementos numa variável de resultado com valor de matriz.
As consultas de várias fases estão sujeitas às mesmas limitações que as consultas de estatísticas:
Consultas de estatísticas: 120 consultas por hora (API e IU)
Visualizações de pesquisa do Google SecOps: 100 visualizações por minuto
As junções de várias fases são suportadas na interface do utilizador e na API
EventService.UDMSearch, mas não na APISearchService.UDMSearch. As consultas de várias fases sem junções também são suportadas na interface do utilizador.
Limitações globais e de eventos
Máximo de eventos:
As consultas de várias fases estão estritamente limitadas no número de eventos que podem processar em simultâneo:
Eventos da UDM: é permitido um máximo de 2 eventos da UDM.
Eventos do gráfico de contexto de entidades (ECG): é permitido um máximo de um evento do ECG.
Limitações de consultas globais:
Estes limites são restrições ao nível da plataforma que controlam a antiguidade e a quantidade de dados que uma consulta de várias fases pode devolver.
Para um intervalo de tempo de consulta, o intervalo de tempo máximo para uma consulta padrão é de 30 dias.
O tamanho máximo total do conjunto de resultados é de 10 000 resultados.
Exemplos de consultas de várias fases
Os exemplos nesta secção ajudam a ilustrar como pode criar uma consulta YARA-L de várias fases completa.
Exemplo: pesquisar ligações de rede invulgarmente ativas (horas)
Este exemplo de YARA-L de várias fases identifica pares de endereços IP com atividade de rede superior ao normal, segmentando pares que mantêm uma atividade elevada durante mais de três horas. A consulta inclui dois componentes obrigatórios: a fase denominada hourly_stats e a fase root.
A fase hourly_stats procura pares principal.ip e target.ip com níveis elevados de atividade de rede.
Esta fase devolve um único valor por hora para os seguintes campos:
Estatísticas do IP de origem (string):
$hourly_stats.src_ipEstatísticas do IP de destino (string):
$hourly_stats.dst_ipEstatísticas para a contagem de eventos (número inteiro):
$hourly_stats.countDesvio padrão de bytes recebidos (float):
$hourly_stats.std_recd_bytesMédia de bytes recebidos (número de vírgula flutuante):
$hourly_stats.avg_recd_bytesHora de início do intervalo de horas em segundos desde o início da época Unix (número inteiro):
$hourly_stats.window_startHora de fim do intervalo de horas em segundos desde o início da época Unix (número inteiro):
$hourly_stats.window_end
A fase raiz processa o resultado da fase hourly_stats. Calcula estatísticas para pares principal.ip e target.ip com atividade que excede o limite especificado por $hourly_stats. Em seguida, filtra os pares com mais de
três horas de atividade elevada.
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
Se alterar a condição de correspondência na fase raiz da seguinte forma, pode introduzir uma agregação com janelas por dia para a consulta de várias fases.
match:
$src_ip, $dst_ip by day
Exemplo: pesquisar ligações de rede invulgarmente ativas (usando a pontuação Z)
Esta consulta de várias fases compara a atividade de rede média diária com a atividade de hoje através de um cálculo da pontuação Z (que mede o número de desvios padrão em relação à média). Esta consulta pesquisa efetivamente atividade de rede invulgarmente elevada entre recursos internos e sistemas externos.
Pré-requisito: o período de tempo da consulta tem de ser igual ou superior a 2 dias e incluir o dia atual para que a pontuação Z calculada seja eficaz.
Esta consulta de várias fases inclui a fase daily_stats e a fase root, que funcionam em conjunto para calcular a pontuação Z da atividade de rede:
A fase
daily_statsrealiza a agregação diária inicial. Calcula o total de bytes trocados todos os dias para cada par de IPs (sourceetarget) e devolve os seguintes campos de fase (correspondentes às colunas nas linhas de saída):$daily_stats.source: singular, string$daily_stats.target: singular, string$daily_stats.exchanged_bytes: singular, integer$daily_stats.window_start: singular, integer$daily_stats.window_end: singular, integer
A fase raiz agrega o resultado da fase
daily_statspara cada par de IPs. Calcula a média e o desvio padrão dos bytes diários trocados em todo o intervalo de pesquisa, juntamente com os bytes trocados hoje. Usa esses três valores calculados para determinar a pontuação Z.A saída apresenta as pontuações Z de todos os pares de IPs de hoje, ordenadas por ordem 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
Exporte variáveis não agregadas de fases
As fases com nome podem incluir uma secção outcome não agregada. Isto significa que as variáveis definidas nessa secção outcome são produzidas diretamente a partir da fase, permitindo que as fases subsequentes acedam às mesmas como campos de fase sem necessitar de uma agregação agrupada.
Exemplo: exporte uma variável não agregada
Este exemplo demonstra como exportar variáveis não agregadas. Tenha em atenção a seguinte lógica:
top_5_bytes_sentde preparação de pesquisas para os cinco eventos com a atividade de rede mais elevada.A fase
top_5_bytes_sentproduz os seguintes campos da fase correspondentes às colunas nas linhas de saída:$top_5_bytes_sent.bytes_sent: singular, integer$top_5_bytes_sent.timestamp_seconds: singular, integer
A fase
rootcalcula as datas/horas mais recentes e mais antigas dos cinco eventos com a atividade de rede mais elevada.
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))
Implemente janelas em consultas de várias fases
As consultas de várias fases suportam todos os tipos de janelas (hop, deslizantes e de agrupamento) em fases com nome. Se uma fase com nome incluir uma janela, o início e o fim da janela para cada linha de saída são acessíveis através dos seguintes campos reservados:
$<stage name>.window_start$<stage name>.window_end
Exemplo: janela de salto
O exemplo seguinte ilustra como pode usar janelas de salto numa consulta de várias fases:
hourly_statsprepara as pesquisas para pares de IPs que têm uma atividade de rede elevada na mesma hora.hourly_statsproduz os seguintes campos de fase correspondentes às colunas nas linhas de saída:$hourly_stats.src_ip: singular, string$hourly_stats.dst_ip: singular, string$hourly_stats.count: singular, integer$hourly_stats.std_recd_bytes: singular, float$hourly_stats.avg_recd_bytes: singular, float$hourly_stats.window_start: singular, integer$hourly_stats.window_end: singular, integer
A fase raiz filtra os pares de IPs com mais de 3 horas de atividade elevada. As horas podem sobrepor-se devido à utilização de um período de intervalo na fase
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 conhecidos
Recomendamos que reveja as seguintes limitações e soluções alternativas recomendadas quando implementar consultas de várias fases:
Todas as consultas de várias fases comportam-se como consultas de pesquisa de estatísticas (o resultado consiste em estatísticas agregadas em vez de eventos não agregados ou linhas da tabela de dados).
O desempenho das junções com eventos de UDM e de entidades de um lado pode ter um desempenho baixo devido à dimensão desse conjunto de dados. Recomendamos vivamente que filtre os eventos da UDM e da entidade do lado da junção o máximo possível (por exemplo, filtre por tipo de evento).
Para orientações gerais sobre práticas recomendadas, consulte o artigo Práticas recomendadas do Yara-L e, para informações específicas sobre junções, consulte o artigo Práticas recomendadas.
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais da Google SecOps.