Problemas conhecidos e limitações do YARA-L 2.0

Este documento é destinado a engenheiros de detecção que querem depurar a lógica de regras e otimizar a execução do YARA-L 2.0. Ele explica como lidar com comportamentos não padrão do mecanismo, como a descompactação de campos, a expansão do produto cartesiano em agregações e a consistência posterior do enriquecimento. Ao seguir esses métodos, você pode evitar erros lógicos que levam a valores de resultado inflacionados ou detecções perdidas.

O YARA-L 2.0 usa um modelo de execução específico em que os campos repetidos são expandidos em linhas de eventos individuais durante a avaliação. Como essa transformação acontece no nível do mecanismo, a referência a vários campos repetidos ou a execução de operações aritméticas em tipos de UDM não assinados exigem soluções alternativas de sintaxe específicas para evitar erros de compilador ou conjuntos de resultados incorretos. Este documento descreve essas restrições técnicas e os padrões lógicos necessários para resolvê-las.

Antes de começar

Verifique se sua conta tem os seguintes direitos técnicos antes de testar ou modificar as regras do YARA-L 2.0:

Papéis do IAM obrigatórios

  • roles/chronicle.viewer (Leitor de operações de segurança): para visualizar regras e metadados de detecção.
  • roles/chronicle.editor (Editor de operações de segurança): para modificar a lógica de regras e salvar alterações.

Permissões necessárias

  • chronicle.rules.runTest: necessária para executar o recurso Executar teste em dados históricos.

  • chronicle.detections.get: para inspecionar a saída de eventos descompactados no painel de detecção.

Terminologia importante

  • UDM (modelo de dados unificado) : o esquema normalizado usado para estruturar toda a telemetria de segurança ingerida na plataforma.
  • Descompactação:a expansão no nível do mecanismo de um único evento de UDM que contém um campo repetido (matriz) em várias linhas. Cada linha representa um elemento exclusivo da matriz, o que pode levar à multiplicação de linhas durante a avaliação de regras.
  • T₀ (execução inicial) : a primeira execução de uma regra na telemetria recebida. Isso ocorre durante a fase de "streaming", geralmente antes que os processos de enriquecimento em segundo plano (como GeoIP ou ASN) sejam finalizados.

Agregações de resultados com descompactação de campos repetidos

Quando uma regra referencia um campo repetido em uma variável de evento com vários elementos, cada elemento é dividido em uma linha de evento separada.

Por exemplo, os dois endereços IP no campo repetido target.ip no evento $e são divididos em duas instâncias de $e, cada uma com um valor target.ip diferente.

rule outbound_ip_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $outbound_ip_count = count($e.target.ip) // yields 2.

  condition:
    $e
}

Registros de eventos: antes e depois da descompactação

As tabelas nesta seção demonstram como um único evento que contém uma matriz de endereços IP é transformado em dois registros distintos.

Antes da descompactação

A tabela a seguir mostra o registro de eventos antes da descompactação do campo repetido:

metadata.id principal.application target.ip
aaaaaaaaa Google SecOps [192.0.2.20, 192.0.2.28]

Depois da descompactação

A tabela a seguir mostra o registro de eventos após a descompactação do campo repetido:

metadata.id principal.application target.ip
aaaaaaaaa Google SecOps 192.0.2.20
aaaaaaaaa Google SecOps 192.0.2.28

Campos repetidos aninhados (produto cartesiano)

Quando uma regra referencia um campo repetido aninhado em outro, como security_results.action, a descompactação ocorre nos dois níveis (pai e filho) simultaneamente. Isso resulta em um produto cartesiano de todos os elementos.

No exemplo a seguir, um evento $e com dois valores repetidos em security_results e dois valores repetidos em security_results.actions são descompactados em quatro instâncias.

rule security_action_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $security_action_count = count($e.security_results.actions) // yields 4.

  condition:
    $e
}

Registro de eventos antes da descompactação aninhada

O registro original armazena as ações em uma estrutura de matriz aninhada.

metadata.id principal.application security_results
aaaaaaaaa Google SecOps [ { actions: [ ALLOW, FAIL ] }, { actions: [ CHALLENGE, BLOCK ] } ]

Registros de eventos após a descompactação aninhada

Após a expansão, cada ação exclusiva se torna uma linha própria, o que pode levar a contagens inesperadas em agregações não distintas.

metadata.id principal.application security_results.actions
aaaaaaaaa Google SecOps PERMITIR
aaaaaaaaa Google SecOps REPROVADO
aaaaaaaaa Google SecOps DESAFIO
aaaaaaaaa Google SecOps BLOQUEAR

Impacto em campos não relacionados

Esse comportamento de descompactação na avaliação de regras pode produzir agregações de resultados inesperadas quando a regra referencia um ou mais campos repetidos com um campo pai que também é um campo repetido. Agregações não distintas, como sum(), array() e count(), não podem considerar valores duplicados em outros campos no mesmo evento produzido pelo comportamento de descompactação.

No exemplo a seguir, o evento $e tem um único nome de host (google.com), mas o resultado (hostnames) agrega quatro instâncias descompactadas do mesmo evento $e, cada uma com um valor principal.hostname duplicado. Esse resultado gera quatro nomes de host (em vez de um) devido à descompactação de valores repetidos em security_results.actions.

rule security_action_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $hostnames = array($e.principal.hostname) // yields 4.
    $security_action_count = count($e.security_results.action) // yields 4.

  condition:
    $e
}

Registro de eventos antes da descompactação com campos não relacionados

O nome do host é um valor único, mas fica ao lado dos resultados de segurança repetidos.

metadata.id principal.application principal.hostname security_results
aaaaaaaaa Google SecOps google.com [ { action: [ ALLOW, FAIL ] }, { action: [ CHALLENGE, BLOCK ] } ]

Registro de eventos após a descompactação com campos não relacionados

O nome do host agora é duplicado em quatro linhas, fazendo com que a função array() o selecione quatro vezes.

metadata.id principal.application principal.hostname security_results.action
aaaaaaaaa Google SecOps google.com PERMITIR
aaaaaaaaa Google SecOps google.com REPROVADO
aaaaaaaaa Google SecOps google.com DESAFIO
aaaaaaaaa Google SecOps google.com BLOQUEAR

Solução alternativa para o comportamento de descompactação

Para garantir que os valores de resultado sejam precisos quando a descompactação ocorrer, use a versão distinta da agregação selecionada. As funções a seguir ignoram as linhas duplicadas criadas pela descompactação:

  • max()
  • min()
  • array_distinct()
  • count_distinct()

Agregações de resultados com várias variáveis de evento

Se uma regra contiver várias variáveis de evento, haverá um item separado na agregação para cada combinação de eventos incluída na detecção. Por exemplo, se a seguinte regra de exemplo for executada nos eventos listados:

events:
  $e1.field = $e2.field
  $e2.somefield = $ph

match:
  $ph over 1h

outcome:
   $some_outcome = sum(if($e1.otherfield = "value", 1, 0))

condition:
  $e1 and $e2
event1:
  // UDM event 1
  field="a"
  somefield="d"

event2:
  // UDM event 2
  field="b"
  somefield="d"

event3:
  // UDM event 3
  field="c"
  somefield="d"

A soma é calculada em todas as combinações de eventos, permitindo que você use as duas variáveis de evento nos cálculos de valor de resultado. Os seguintes elementos são usados no cálculo:

1: $e1 = event1, $e2 = event2
2: $e1 = event1, $e2 = event3
3: $e1 = event2, $e2 = event1
4: $e1 = event2, $e2 = event3
5: $e1 = event3, $e2 = event1
5: $e1 = event3, $e2 = event2

Isso resulta em uma soma máxima potencial de 6, mesmo que $e2 só possa corresponder a 3 eventos distintos.

Isso afeta a soma, a contagem e a matriz. Para contagem e matriz, o uso de count_distinct ou array_distinct pode resolver o problema, mas não há solução alternativa para a soma.

Parênteses no início de uma expressão

Não é possível começar uma expressão com parênteses, e isso aciona um erro de análise no editor de regras.

Sintaxe inválida

parsing: error with token: ")"
invalid operator in events predicate

O exemplo a seguir gera esse tipo de erro:

($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600 > 1

Variações de sintaxe válidas

As seguintes variações de sintaxe retornam o mesmo resultado, mas com sintaxe válida:

$event.metadata.ingested_timestamp.seconds / 3600 -
$event.metadata.event_timestamp.seconds / 3600 > 1
    1 / 3600 * ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) > 1
    1 < ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600

A matriz de índice no resultado exige agregação

Não é permitido indexar diretamente uma matriz na seção outcome para campos repetidos. Ela exige uma variável de marcador temporário.

outcome:
  $principal_user_dept = $suspicious.principal.user.department[0]

Alternativa

Capture o índice de matriz específico em uma variável de marcador na seção events e, em seguida, referencie esse marcador no resultado.

events:
  $principal_user_dept = $suspicious.principal.user.department[0]

outcome:
  $principal_user_department = $principal_user_dept

Condição OR com não existência

Se você aplicar uma condição OR entre duas variáveis de evento separadas e se a regra corresponder à não existência, a regra será compilada com sucesso, mas poderá produzir detecções de falsos positivos.

Por exemplo, a seguinte sintaxe de regra pode corresponder a eventos que têm $event_a.field = "something", mesmo que não deva:

events:
     not ($event_a.field = "something" **or** $event_b.field = "something")
condition:
     $event_a and #event_b >= 0

Alternativa

Separe as verificações de não existência em blocos individuais para cada variável para manter a integridade lógica.

events:
  not ($event_a.field = "something")
  not ($event_b.field = "something")

condition:
  $event_a and #event_b >= 0

Operações aritméticas com campos de eventos não assinados

Se você tentar usar uma constante inteira em uma operação aritmética com um campo de UDM cujo tipo seja um número inteiro não assinado, vai receber um erro. Por exemplo:

events:
  $total_bytes = $e.network.received_bytes * 2

As constantes inteiras padrão são definidas como números inteiros assinados, que são incompatíveis com campos de UDM definidos como números inteiros não assinados, como network.received_bytes.

Alternativa

É possível ignorar esse erro forçando a constante inteira a se comportar como um float por meio de uma operação de divisão.

events:
  $total_bytes = $e.network.received_bytes * (2/1)

Enriquecimento de GeoIP e consistência posterior

O sistema prioriza a velocidade em vez da precisão imediata nos estágios iniciais de enriquecimento (streaming e sensível à latência), o que pode levar à perda de dados e a possíveis falsos positivos. O sistema continua a enriquecer os dados em segundo plano, mas os dados podem não estar disponíveis quando a regra é executada. Isso faz parte do processo normal de consistência posterior.

Para evitar falsos positivos causados pelo atraso de enriquecimento, verifique explicitamente se o campo não está vazio antes de avaliar o valor dele.

Por exemplo, considere este evento de regra:

$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"

A regra depende do fato de que o evento precisa ter $e.principal.ip_geo_artifact.network.asn = "16509" E $e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom", que são campos enriquecidos. Se o enriquecimento não for concluído a tempo, a regra vai produzir um falso positivo.

Para evitar isso, uma verificação melhor para essa regra seria:

$e.principal.ip_geo_artifact.network.asn != "" AND
$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region != "" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"

Essa regra elimina a possibilidade de o evento ser acionado por IPs com o ASN 16509, mas localizados fora do Reino Unido. Isso melhora a precisão geral da regra.

Saiba como resolver problemas de atraso de enriquecimento.

Solução de problemas

Esta seção descreve as expectativas de desempenho e fornece correções de autoatendimento para problemas comuns em que o comportamento de detecção ao vivo difere dos resultados do teste.

Eventos futuros

As regras de vários eventos são projetadas para processar eventos em ordem cronológica em relação à ingestão. Se você especificar e ativar uma regra de vários eventos, ela não vai criar detecções para eventos com carimbos de data/hora futuros, por exemplo, quando o event.timestamp tiver uma data e hora definidas após o ingest.timestamp.

Atraso de enriquecimento

O Google SecOps prioriza a velocidade de ingestão para expor alertas iniciais o mais rápido possível. No entanto, os processos de enriquecimento em segundo plano, como a resolução de metadados GeoIP, ASN ou UDM, seguem um modelo de consistência posterior.

Execução inicial (T₀)

O mecanismo ativo pode avaliar uma regra antes que o enriquecimento em segundo plano seja concluído. Dependendo se a lógica depende de campos enriquecidos para detecções ou exclusões, isso pode levar às seguintes discrepâncias temporárias:

  • Falsos negativos (atraso de detecção): esse é um resultado comum. Se uma regra depender de um campo enriquecido para ser acionada (por exemplo, target.user.department == "Finance") e esse campo for null, a regra não vai corresponder durante a execução inicial.

  • Falsos positivos (falha de exclusão): se a regra usar campos enriquecidos para filtrar atividades conhecidas (por exemplo, NOT target.ip_geo_country == "US"), a regra poderá acionar um falso positivo porque os dados de "exclusão" ainda não foram aplicados.

Execuções de correção

Essas execuções em segundo plano reavaliam os dados após um atraso (por exemplo, 45 minutos ou 30 horas). Isso "corrige" os estados de detecção da seguinte maneira:

  • Detecções atrasadas: eventos que eram "falsos negativos" em T₀ agora produzem uma detecção quando o enriquecimento é finalizado.

  • Correção: todos os falsos positivos de T₀ permanecem no sistema, mas os dados totalmente enriquecidos ficam visíveis no visualizador de UDM para triagem manual.

Discrepância de teste de execução

A ferramenta Executar teste opera em dados históricos que já foram reconciliados. Como os dados são totalmente enriquecidos quando você executa um teste manual, é possível conferir os resultados da "correção" imediatamente. Isso significa que você não vai ver os falsos negativos de T₀ ou os falsos positivos baseados em exclusão que ocorreram durante a execução inicial ao vivo.

Correção de erros

Use a tabela a seguir para resolver discrepâncias entre alertas ativos e resultados de testes.

Problema Descrição Correção acionável
Falha de exclusão Uma regra é acionada apesar de uma exclusão (por exemplo, != "ASN_123") porque o campo era nulo durante a execução inicial. Adicione uma verificação não nula à seção de eventos para garantir que os dados sejam enriquecidos antes da avaliação, por exemplo:

$e.principal.ip_geo_artifact.network.asn != ""
Comparação entre correspondência ativa e de teste As regras ativas acionam alertas, mas a execução do teste nos mesmos dados mostra "No Results". Adicione $e.field != "" que verifica todos os campos enriquecidos (GeoIP, ASN, File Path) para sincronizar o comportamento ativo e histórico.
Metadados ausentes As detecções aparecem no painel com campos GeoIP ou File Path vazios. Isso é esperado para execuções T0. Para corrigir, inclua uma verificação field != "" ou aumente o deslocamento da primeira execução na programação para permitir mais tempo para a ingestão.

Validação e teste

Para verificar se uma regra está processando corretamente o enriquecimento atrasado, faça o seguinte:

  1. Identifique o atraso:localize uma detecção que você acredita ser um falso positivo. Na coluna Tipo de detecção, procure o ícone <span class="material-icons">lightbulb</span>. Os alertas sem esse ícone são da execução inicial em que o atraso de enriquecimento é mais comum.

  2. Atualize a lógica de regras: adicione uma verificação field != "" para todos os pontos de dados enriquecidos usados na lógica.
    Exemplo (caminho do arquivo):
    $e.target.process.parent_process.file.full_path != ""

  3. Teste e verifique :

    • Use o recurso Executar teste para garantir que a lógica ainda corresponda aos dados históricos pretendidos.
    • Verifique se a regra agora só é acionada (ou excluída corretamente) durante as execuções de correção depois que os campos de enriquecimento são preenchidos.

Para mais detalhes, consulte Gerenciar a programação de execução de regras e Configurar programações personalizadas para regras.

Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.