Criar consultas de várias etapas em YARA-L
Este documento descreve como as consultas de várias etapas em YARA-L permitem inserir a saída de uma etapa de consulta diretamente na entrada de uma etapa subsequente. Esse processo oferece mais controle sobre a transformação de dados do que uma única consulta monolítica.
Integrar consultas de várias etapas com recursos atuais
As consultas de várias etapas funcionam em conjunto com os seguintes recursos do Google Security Operations:
Regras de detecção compostas: consultas de várias etapas complementam as regras de detecção compostas. Ao contrário das regras compostas, as consultas de várias etapas que usam a Pesquisa podem retornar resultados em tempo real.
Períodos e regras de vários eventos:é possível usar consultas de várias etapas para detectar anomalias comparando diferentes períodos nos seus dados. Por exemplo, você pode usar os estágios iniciais da consulta para estabelecer um valor de referência em um período estendido e, em seguida, usar um estágio posterior para avaliar a atividade recente em relação a esse valor. Também é possível usar regras de vários eventos para criar um tipo de comparação semelhante.
As consultas de várias etapas em YARA-L são compatíveis com Painéis e Pesquisa.
As junções ajudam a correlacionar dados de várias fontes para fornecer mais contexto a uma investigação. Ao vincular eventos, entidades e outros dados relacionados, é possível investigar cenários de ataque complexos. Para mais informações, consulte Usar mesclagens na Pesquisa.
Definir a sintaxe YARA-L de várias etapas
Ao configurar uma consulta de várias etapas, observe o seguinte:
- Etapa de limite: as consultas de várias etapas precisam conter entre 1 e 4 etapas nomeadas, além da etapa raiz.
- Sintaxe de ordem: sempre defina a sintaxe de estágio nomeado antes da sintaxe de estágio raiz.
Criar uma consulta YARA-L de várias etapas
Para criar uma consulta YARA-L de várias etapas, siga estas etapas.
Estrutura e sintaxe de estágio
Acesse Investigação > Pesquisar. Siga estes requisitos estruturais ao definir os estágios da consulta:
Sintaxe: use a seguinte sintaxe para nomear cada etapa e separá-la das outras:
stage <stage name> { }
Chaves: coloque toda a sintaxe de estágio entre chaves {}.
Ordem: defina a sintaxe para todas as etapas nomeadas antes de definir a etapa raiz.
Referência: cada etapa pode referenciar etapas definidas anteriormente na consulta.
Etapa raiz: uma consulta precisa ter uma etapa raiz, que é processada depois de todas as etapas nomeadas.
O exemplo de etapa a seguir, daily_stats, coleta estatísticas diárias da rede:
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)
}
Acessar a saída da etapa de acesso
A saída de um estágio nomeado é acessível aos estágios subsequentes usando campos de estágio. Os campos de etapa correspondem às variáveis match e outcome da etapa e podem ser usados de maneira semelhante aos campos do modelo de dados unificado (UDM).
Use a seguinte sintaxe para acessar um campo de etapa:
$<stage name>.<variable name>
Marcações de tempo da janela de acesso (opcional)
Se um estágio nomeado usar uma janela de salto, deslizante ou rotativa, acesse o início e o fim da janela para cada linha de saída usando estes campos reservados:
$<stage name>.window_start$<stage name>.window_end
Os campos window_start e window_end são números inteiros expressos em segundos desde a era Unix. As janelas em diferentes estágios podem variar de tamanho.
Limitações
As consultas de várias etapas têm as seguintes restrições funcionais e estruturais:
Limites estruturais e de etapa
Etapa raiz: só é permitida uma etapa raiz por consulta.
Estágios nomeados: é possível usar até quatro estágios nomeados.
Referência de etapa: uma etapa só pode referenciar etapas definidas logicamente antes dela na mesma consulta.
Junções: é permitido um máximo de quatro junções que não sejam de tabelas de dados em todas as etapas.
Requisito de resultado: cada etapa nomeada (exceto a raiz) precisa incluir uma seção
matchououtcome. A seçãooutcomenão exige agregação.
Limites de janela e compatibilidade
Suporte a recursos: as consultas de várias etapas são compatíveis com Pesquisa e Painéis, mas não com Regras.
Tipos de janela: evite misturar tipos diferentes de janela em uma única consulta.
Dependência de janela: um estágio que usa uma janela deslizante ou de salto não pode depender de outro estágio que também usa uma janela deslizante ou de salto.
Tamanho da janela de rolagem: embora as janelas de rolagem em diferentes estágios possam variar de tamanho, a diferença precisa ser menor que 720x.
Exemplo: diferença de agregação de estágio
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 etapa monthly_stats agregar dados por mês e a etapa raiz agregar a saída de monthly_stats por minuto, cada linha de monthly_stats será mapeada para 43.200 linhas na etapa raiz (porque há 43.200 minutos em um mês).
Limitações de fase e consulta
Cada etapa individual em uma consulta de várias etapas tem as seguintes restrições:
A maioria das limitações que se aplicam a uma consulta de estágio único também se aplicam a cada estágio individual:
Requisito de saída: cada etapa precisa gerar pelo menos uma variável de correspondência ou resultado (campo de etapa).
Janela na junção: o tamanho máximo da janela (hop, tumbling ou sliding) usado em uma junção é de dois dias.
Número máximo de variáveis de resultado:
20 para clientes que não ativaram o limite maior de variáveis de resultado
50 para clientes que ativaram o limite maior de variáveis de resultado
Número máximo de elementos em uma variável de resultado com valor de matriz.
As consultas de várias etapas estão sujeitas às mesmas limitações das consultas de estatísticas:
Consultas de estatísticas: 120 QPH (API e UI)
Pesquisar visualizações do Google SecOps: 100 visualizações por minuto
As junções de várias etapas são compatíveis com a interface do usuário e a API
EventService.UDMSearch, mas não com a APISearchService.UDMSearch. Consultas de várias etapas sem junções também são compatíveis com a interface do usuário.
Limitações globais e de eventos
Número máximo de eventos:
As consultas de várias etapas são estritamente limitadas no número de eventos que podem processar simultaneamente:
Eventos da UDM: é permitido um máximo de dois eventos da UDM.
Eventos do gráfico de contexto de entidade (ECG): é permitido no máximo um evento de ECG.
Limitações de consultas globais:
Esses limites são restrições em toda a plataforma que controlam a quantidade de dados e o período que uma consulta de várias etapas pode retornar.
Para um período de consulta, o máximo é de 30 dias.
O tamanho máximo do conjunto de resultados é de 10.000 resultados.
Exemplos de consultas de várias etapas
Os exemplos nesta seção ajudam a ilustrar como criar uma consulta YARA-L completa de várias etapas.
Exemplo: pesquisar conexões de rede com atividade incomum (horas)
Este exemplo de várias etapas do YARA-L identifica pares de endereços IP com atividade de rede maior que o normal, segmentando pares que mantêm alta atividade por mais de três horas. A consulta inclui dois componentes obrigatórios: a etapa nomeada, hourly_stats, e a etapa root.
A etapa hourly_stats procura pares principal.ip e target.ip com altos níveis de atividade de rede.
Essa etapa retorna 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 (ponto flutuante):
$hourly_stats.avg_recd_bytesHorário de início do agrupamento por hora em segundos desde a época do Unix (número inteiro):
$hourly_stats.window_startHorário de término do agrupamento por hora em segundos desde a época do Unix (inteiro):
$hourly_stats.window_end
A etapa raiz processa a saída da etapa hourly_stats. Ele calcula estatísticas para pares principal.ip e target.ip com atividade acima do limite especificado por $hourly_stats. Em seguida, ele filtra os pares com mais de três horas de alta atividade.
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 você alterar a condição de correspondência na etapa raiz da seguinte maneira, poderá introduzir uma agregação em janela por dia para a consulta de várias etapas.
match:
$src_ip, $dst_ip by day
Exemplo: pesquisar conexões de rede ativas de maneira incomum (usando a pontuação Z)
Essa consulta de várias etapas compara a atividade média diária da rede com a atividade de hoje usando um cálculo de pontuação Z, que mede o número de desvios padrão da média. Essa consulta pesquisa atividades de rede incomumente altas entre recursos internos e sistemas externos.
Pré-requisito: o período da consulta precisa ser maior ou igual a dois dias e incluir o dia atual para que o escore Z calculado seja eficaz.
Essa consulta de várias etapas inclui as fases daily_stats e root, que trabalham juntas para calcular o escore Z da atividade de rede:
A etapa
daily_statsrealiza a agregação diária inicial. Ele calcula o total de bytes trocados a cada dia para cada par de IP (sourceetarget) e retorna os seguintes campos de estágio (correspondentes às colunas nas linhas de saída):$daily_stats.source: singular, string$daily_stats.target: singular, string$daily_stats.exchanged_bytes: singular, número inteiro$daily_stats.window_start: singular, número inteiro$daily_stats.window_end: singular, número inteiro
A etapa raiz agrega a saída da etapa
daily_statspara cada par de IP. Ele calcula a média e o desvio padrão dos bytes diários trocados em todo o intervalo de pesquisa, além dos bytes trocados hoje. Ele usa esses três valores calculados para determinar o escore Z.A saída lista os escores Z de todos os pares de IP de hoje, classificados em ordem decrescente.
// 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
Exportar variáveis não agregadas de estágios
As etapas nomeadas podem incluir uma seção outcome não agregada. Isso significa que as variáveis definidas nessa seção outcome são geradas diretamente da etapa, permitindo que as etapas subsequentes acessem essas variáveis como campos de etapa sem exigir uma agregação agrupada.
Exemplo: exportar variável não agregada
Este exemplo demonstra como exportar variáveis não agregadas. Observe a seguinte lógica:
top_5_bytes_sentestágios de pesquisa para os cinco eventos com maior atividade de rede.A etapa
top_5_bytes_sentgera os seguintes campos de etapa correspondentes às colunas nas linhas de saída:$top_5_bytes_sent.bytes_sent: singular, número inteiro$top_5_bytes_sent.timestamp_seconds: singular, número inteiro
A etapa
rootcalcula os carimbos de data/hora mais recentes e mais antigos dos cinco eventos com maior atividade de rede.
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))
Implementar janelamento em consultas de várias etapas
As consultas de várias etapas oferecem suporte a todos os tipos de janelas (hop, deslizante e rotativa) em etapas nomeadas. Se um estágio nomeado incluir uma janela, o início e o fim dela para cada linha de saída poderão ser acessados usando os seguintes campos reservados:
$<stage name>.window_start$<stage name>.window_end
Exemplo: janela de salto
O exemplo a seguir ilustra como usar janelas de salto em uma consulta de várias etapas:
A etapa
hourly_statsprocura pares de IP com alta atividade de rede na mesma hora.hourly_statsgera os seguintes campos de etapa correspondentes às colunas nas linhas de saída:$hourly_stats.src_ip: singular, string$hourly_stats.dst_ip: singular, string$hourly_stats.count: singular, número inteiro$hourly_stats.std_recd_bytes: singular, ponto flutuante$hourly_stats.avg_recd_bytes: singular, ponto flutuante$hourly_stats.window_start: singular, número inteiro$hourly_stats.window_end: singular, número inteiro
A etapa raiz filtra pares de IP com mais de três horas de alta atividade. As horas podem estar se sobrepondo devido ao uso de uma janela de salto na 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 conhecidos
Recomendamos que você analise as seguintes limitações e soluções alternativas ao implementar consultas de várias etapas:
Todas as consultas de várias etapas se comportam como consultas de pesquisa de estatísticas. A saída consiste em estatísticas agregadas, e não em eventos não agregados ou linhas da tabela de dados.
A performance das junções com UDM e eventos de entidade de um lado pode ser baixa devido ao tamanho desse conjunto de dados. Recomendamos filtrar o lado dos eventos de UDM e entidade da junção o máximo possível (por exemplo, filtrar por tipo de evento).
Para orientações gerais sobre práticas recomendadas, consulte Práticas recomendadas da Yara-L. Para informações específicas sobre junções, consulte Práticas recomendadas.
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.