Crie consultas de várias fases em YARA-L

Compatível com:

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 match ou uma secção outcome. A secção outcome nã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:

  • 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 API SearchService.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_ip

  • Estatísticas do IP de destino (string): $hourly_stats.dst_ip

  • Estatísticas para a contagem de eventos (número inteiro): $hourly_stats.count

  • Desvio padrão de bytes recebidos (float): $hourly_stats.std_recd_bytes

  • Média de bytes recebidos (número de vírgula flutuante): $hourly_stats.avg_recd_bytes

  • Hora de início do intervalo de horas em segundos desde o início da época Unix (número inteiro): $hourly_stats.window_start

  • Hora 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_stats realiza a agregação diária inicial. Calcula o total de bytes trocados todos os dias para cada par de IPs (source e target) 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_stats para 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_sent de preparação de pesquisas para os cinco eventos com a atividade de rede mais elevada.

  • A fase top_5_bytes_sent produz 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 root calcula 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_stats prepara as pesquisas para pares de IPs que têm uma atividade de rede elevada na mesma hora.

  • hourly_stats produz 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.