Expressões, operadores e outras construções

Suportado em:

Este documento inclui informações para ajudar a criar regras e consultas YARA-L com expressões.

Expressões booleanas

As expressões booleanas são expressões com um tipo booleano, que inclui expressões de comparação, expressões de funções e expressões de listas de referências ou tabelas de dados. Pode usar expressões booleanas na secção events e outcome numa regra ou consulta YARA-L.

Expressões de comparação

As expressões de comparação são expressões que aplicam um operador de comparação a duas expressões. As expressões podem ser campos de eventos, variáveis, literais ou expressões de funções.

Exemplo: expressões de comparação

$e.source.hostname = "host1234"
$e.source.port < 1024
1024 < $e.source.port
$e1.source.hostname != $e2.target.hostname
$e1.metadata.collected_timestamp.seconds > $e2.metadata.collected_timestamp.seconds
$port >= 25
$host = $e2.target.hostname
"google-test" = strings.concat($e.principal.hostname, "-test")
"email@google.org" = re.replace($e.network.email.from, "com", "org")

Expressões de funções

Algumas expressões de funções devolvem um valor booleano, que pode ser usado como um predicado individual na secção events, como:

re.regex()

net.ip_in_range_cidr()

Exemplo: expressões de funções

re.regex($e.principal.hostname, `.*\.google\.com`)
net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")

Lista de referências ou tabela de dados

Pode usar listas de referências ou tabelas de dados nas secções events ou outcome. Consulte os artigos Listas de referências e Use tabelas de dados para mais informações sobre o comportamento e a sintaxe das listas de referências e das tabelas de dados.

Exemplo: sintaxe para listas de referências

Os exemplos seguintes mostram a sintaxe para vários tipos de listas de referência numa consulta:

// STRING reference list
$e.principal.hostname in %string_reference_list

// REGEX reference list
$e.principal.hostname in regex %regex_reference_list

// CIDR reference list
$e.principal.ip in cidr %cidr_reference_list

Exemplo: sintaxe para tabelas de dados

// STRING data table
$e.target.hostname in %data_table_name.column_name

// REGEX data table
$e.target.hostname in regex %regex_table_name.column_name

// CIDR data table
$e.principal.ip in cidr %cidr_table_name.column_name

Exemplo: use not e nocase na sintaxe das listas de referências

// Exclude events whose hostnames match substrings in my_regex_list.
not $e.principal.hostname in regex %my_regex_list

// Event hostnames must match at least 1 string in my_string_list (case insensitive).
$e.principal.hostname in %my_string_list nocase

O operador nocase é compatível com listas STRING e listas REGEX.

Por motivos de desempenho, a utilização de listas de referência e tabelas de dados tem as seguintes limitações:

  • Máximo de in declarações numa consulta, com ou sem operadores especiais: 7
  • Máximo de declarações in com o operador regex: 4
  • Máximo de in declarações com o operador cidr: 2

Expressões lógicas

Pode usar os operadores lógicos and e or na secção events.

Exemplo: expressões lógicas

$e.metadata.event_type = "NETWORK_DNS" or $e.metadata.event_type = "NETWORK_DHCP"
($e.metadata.event_type = "NETWORK_DNS" and $e.principal.ip = "192.0.2.12") or ($e.metadata.event_type = "NETWORK_DHCP" and $e.principal.mac = "AB:CD:01:10:EF:22")
not $e.metadata.event_type = "NETWORK_DNS"

Por predefinição, a ordem de precedência do mais alto para o mais baixo é not, and e or. Por exemplo, "a ou b e c" é avaliado como "a ou (b e c)" quando os operadores or e and são definidos explicitamente na expressão.

Na secção events, os predicados são unidos através do operador and se um operador não estiver definido explicitamente. A ordem de avaliação pode ser diferente se o operador and estiver implícito na expressão. Considere as seguintes expressões de comparação em que or está definido explicitamente e o operador and está implícito.

$e1.field = "bat"
or $e1.field = "baz" 
$e2.field = "bar"

É interpretado da seguinte forma:

($e1.field = "bat" or $e1.field = "baz")
and ($e2.field = "bar")

Como or está definido explicitamente, os predicados circundantes são agrupados e avaliados primeiro. O último predicado, $e2.field = "bar". É adicionado implicitamente através do and. O resultado é que a ordem de avaliação muda.

Tipos enumerados

Pode usar os operadores com tipos enumerados. Pode ser aplicado a regras para simplificar e otimizar o desempenho (use o operador em vez de listas de referência).

No exemplo seguinte, "USER_UNCATEGORIZED" e "USER_RESOURCE_DELETION" correspondem a 15000 e 15014, pelo que a regra vai procurar todos os eventos listados:

$e.metadata.event_type >= "USER_CATEGORIZED" and $e.metadata.event_type <= "USER_RESOURCE_DELETION"

Modificador Nocase

Para ignorar a capitalização numa expressão de comparação entre valores de string ou uma expressão regular, acrescente nocase ao final da expressão, conforme mostrado nos exemplos seguintes.

Exemplo: modificador nocase

$e.principal.hostname != "http-server" nocase
$e1.principal.hostname = $e2.target.hostname nocase
$e.principal.hostname = /dns-server-[0-9]+/ nocase
re.regex($e.target.hostname, `client-[0-9]+`) nocase

O modificador nocase não pode ser usado quando o tipo de campo é um valor enumerado. Os seguintes exemplos são inválidos e geram erros de compilação:

$e.metadata.event_type = "NETWORK_DNS" nocase
$e.network.ip_protocol = "TCP" nocase

Comentários

Os comentários podem ser usados em consultas para fornecer mais informações. Usa o caráter de barra para indicar um comentário:

  • Para um comentário de uma única linha, use dois carateres de barra (// comment).
  • Para um comentário de várias linhas, use o caráter de barra (/) e o caráter de asterisco (*) (/* comment */).

Literals

O YARA-L suporta números inteiros e de vírgula flutuante não negativos, strings, valores booleanos e literais de expressões regulares. Os literais são valores fixos usados nas condições de consulta. O YARA-L também usa outras construções semelhantes a literais, como expressões regulares (delimitadas por barras invertidas) para correspondência de padrões e booleanos (verdadeiro/falso) para lógica.

Literais de string

Os literais de string são sequências de carateres entre aspas duplas (") ou plicas (`). A string é interpretada de forma diferente, consoante o tipo de aspas que usar:

  • Aspas duplas ("hello\tworld"): use para strings normais. Os carateres de escape têm de ser incluídos, em que \t é interpretado como uma tabulação.
  • Aspas graves (`hello\tworld`): use quando todos os carateres devem ser interpretados literalmente, em que \t não é interpretado como uma tabulação.

Literais de expressões regulares

Para os literais de expressões regulares, tem duas opções:

  • Se quiser usar expressões regulares diretamente sem a função re.regex(), use /regex/ para os literais de expressões regulares.

  • Se quiser usar literais de strings como literais de expressões regulares, use a função re.regex(). Tenha em atenção que, para strings literais com aspas duplas, tem de usar carateres de barra invertida como escape para carateres de barra invertida, o que pode parecer estranho.

Os exemplos seguintes mostram expressões regulares equivalentes:

re.regex($e.network.email.from, `.*altostrat\.com`)

re.regex($e.network.email.from, ".*altostrat\\.com")

$e.network.email.from = /.*altostrat\.com/

A Google recomenda a utilização de carateres de acento grave para strings em expressões regulares para facilitar a leitura.

Operadores

Operador Descrição
= igual/declaração
!= não é igual
< inferior a
<= inferior ou igual a
> superior a
>= maior ou igual

Variáveis

No YARA-L, todas as variáveis usam a sintaxe $<variable name>. Os seguintes tipos de variáveis podem ser usados em YARA-L.

Variáveis de eventos

As variáveis de eventos representam grupos de eventos ou eventos de entidades. Especifica condições para variáveis de evento na secção events através de um nome, uma origem do evento e campos de eventos.

  • As origens de eventos são udm (para eventos normalizados) e graph (para eventos de entidades). Se a origem for omitida, udm é definida como a origem predefinida.

  • Os campos de eventos são representados como uma cadeia de .<field name> (por exemplo, $e.field1.field2) e as cadeias de campos começam sempre na origem de nível superior (UDM ou entidade).

Variáveis de correspondência

As variáveis de correspondência são usadas na secção match para agrupar eventos com base em valores comuns num período especificado.

Tornam-se campos de agrupamento para a consulta, uma vez que é devolvida uma linha para cada conjunto único de variáveis de correspondência (e para cada intervalo de tempo). Quando a consulta encontra uma correspondência, são devolvidos os valores das variáveis de correspondência.

Especifica o que cada variável de correspondência representa na secção events.

Variáveis de marcadores de posição

As variáveis de marcadores de posição são usadas para captar e armazenar valores específicos dos campos de eventos da UDM para serem referenciados e usados ao longo de uma consulta. São usados para associar eventos distintos, especialmente em consultas com vários eventos. Ao atribuir um valor comum (por exemplo, userid ou hostname) a um marcador de posição, pode usar este marcador de posição na secção match para agrupar eventos que partilham esse valor num período especificado.

Define variáveis de marcadores de posição na secção events atribuindo o valor de um campo UDM a um nome de variável com o prefixo $ (por exemplo: $targetUser = $e.target.user.userid).

Também pode definir variáveis de marcadores de posição nas seguintes secções:

  • condition para especificar as condições de correspondência.
  • outcome para fazer cálculos, definir métricas ou extrair pontos de dados específicos dos eventos correspondentes.
  • Secção match para agrupar eventos por valores comuns.

Keywords

No YARA-L, as palavras-chave são palavras reservadas que definem a estrutura e a lógica de uma consulta de deteção. São usados para especificar diferentes secções de uma consulta, realizar operações lógicas e matemáticas, e definir condições para eventos correspondentes. Não é possível usar estas palavras-chave como identificadores para consultas, strings ou variáveis.

As palavras-chave não são sensíveis a maiúsculas e minúsculas (por exemplo, and e AND são equivalentes).

Categorias principais de palavras-chave YARA-L 2.0

Esta lista não é exaustiva, mas abrange as palavras-chave principais usadas no YARA-L 2.0 para criar consultas de deteção robustas.

  • Definição da consulta:
    • rule: inicia a definição de uma nova consulta YARA-L.
    • private: designa uma consulta como privada, impedindo que seja exposta diretamente ou acionada externamente.
    • global: marca uma consulta como global, indicando que deve ser aplicada de forma abrangente.
  • Secções de consulta:
    • meta: introduz a secção de metadados para informações descritivas sobre a consulta.
    • strings: denota a secção onde os padrões de strings estão definidos.
    • condition: especifica a secção que contém a lógica booleana para o acionamento de consultas.
    • events: define a secção para especificar variáveis de eventos e as respetivas condições.
    • match: apresenta a secção para agregar valores num período.
    • outcome: define a secção para adicionar contexto e classificação às consultas acionadas.
  • Modificadores de strings:
    • ascii: especifica que uma string deve ser correspondida como texto ASCII.
    • wide: indica que uma string deve ser correspondida como carateres largos (UTF-16).
    • nocase: faz uma correspondência de strings sem distinção entre maiúsculas e minúsculas.
    • fullword: requer que a string corresponda a uma palavra completa.
    • xor: aplica a transformação XOU à string antes da correspondência.
    • base64, base64wide: aplica a codificação Base64 antes da correspondência.
  • Operadores lógicos:
    • and, or, not: operadores lógicos booleanos padrão para combinar condições.
    • all of, any of: usado para avaliar várias expressões numa condição.
  • Operadores de comparação e relacionais:
    • at: especifica um desvio exato para a correspondência de strings.
    • contains: verifica se uma string contém uma substring.
    • startswith, endswith: verifica se uma string começa ou termina com uma substring.
    • icontains, istartswith, iendswith, iequals: versões sem distinção entre maiúsculas e minúsculas.
    • matches: usado para correspondência de expressões regulares.
  • Tipos de dados e especificadores de tamanho:
    • int8, uint8, int16, uint16, int32, uint32: tipos de números inteiros com tamanhos especificados.
    • int8be, uint8be, int16be, uint16be, int32be, uint32be: versões big-endian de tipos de números inteiros.
    • filesize: representa o tamanho do ficheiro que está a ser analisado.
    • entrypoint: refere-se ao ponto de entrada de um ficheiro executável.

Maps

O YARA-L suporta mapas para os tipos de dados Struct e Label, que são usados em alguns campos do UDM.

Para pesquisar um par de chave/valor específico nos tipos de dados Struct e Label, use a sintaxe de mapa padrão:

  • Sintaxe do campo Struct: $e.udm.additional.fields["pod_name"] = "kube-scheduler"
  • Sintaxe do campo de etiqueta: $e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"

Exemplo: utilização válida e inválida de mapas

Os exemplos seguintes mostram a utilização válida e inválida de mapas.

Utilização válida de mapas

Usar um campo Struct na secção de eventos:

events:
  $e.udm.additional.fields["pod_name"] = "kube-scheduler"
  

Usar um campo de etiqueta na secção de resultados:

outcome:
  $value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])
 

Atribuir um valor de mapa a um marcador de posição:

$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]

Usar um campo de mapa numa condição de junção:

// using a Struct field in a join condition between two udm events $u1 and $u2
$u1.metadata.event_type = $u2.udm.additional.fields["pod_name"]

Utilização não suportada de mapas

Combinar palavras-chave any ou all com um mapa

all $e.udm.additional.fields["pod_name"] = "kube-scheduler"

Outros tipos de valores

A sintaxe de mapa só pode devolver um valor de string. No caso dos tipos de dados [Struct](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#struct), a sintaxe de mapa só pode aceder a chaves cujos valores sejam strings. Não é possível aceder a chaves cujos valores sejam outros tipos primitivos, como números inteiros.

Processamento de valores duplicados nos mapas

O acesso ao mapa destina-se a obter um único valor associado a uma chave específica. Este é o comportamento padrão e esperado. No entanto, em situações raras e pouco comuns, o contexto do elemento map access pode apontar inadvertidamente para vários valores. No caso limite invulgar em que o acesso ao mapa se refere a vários valores, map access devolve deterministicamente o primeiro valor. Isto pode acontecer se uma etiqueta tiver uma chave duplicada ou uma etiqueta tiver um campo repetido de antepassado.

A etiqueta tem uma chave duplicada

A estrutura da etiqueta representa um mapa, mas não aplica a unicidade da chave. Por convenção, um mapa deve ter chaves únicas, pelo que o Google SecOps não recomenda o preenchimento de uma etiqueta com chaves duplicadas.

Exemplo: etiqueta com chave duplicada

O texto da consulta $e.metadata.ingestion_labels["dupe-key"] devolveria o primeiro valor possível, val1, se fosse executado no seguinte exemplo de dados:

    // Disrecommended usage of label with a duplicate key:
    event {
      metadata{
        ingestion_labels{
          key: "dupe-key"
          value: "val1" // This is the first possible value for "dupe-key"
        }
        ingestion_labels{
          key: "dupe-key"
          value: "val2"
        }
      }
    }
  

A etiqueta tem um campo repetido de antepassado

Um campo repetido pode conter uma etiqueta como um campo secundário. Duas entradas diferentes no campo repetido de nível superior podem conter etiquetas com a mesma chave.

Exemplo: etiqueta com campo repetido de ancestral

O texto da consulta $e.security_result.rule_labels["key"] devolveria o primeiro valor possível, "val3", se fosse executado no seguinte exemplo de dados:

    event {
      // security_result is a repeated field.
      security_result {
        threat_name: "threat1"
        rule_labels {
          key: "key"
          value: "val3" // This is the first possible value for "key"
        }
      }
      security_result {
        threat_name: "threat2"
        rule_labels {
          key: "key"
          value: "val4"
        }
      }
    }
  

Aceda às variáveis de resultados nos mapas

Esta secção explica como aceder às variáveis de resultados nos mapas como os respetivos tipos de dados originais (por exemplo, números inteiros, booleanos ou listas destes tipos) em vez de apenas strings. Pode usar esta funcionalidade para ter mais flexibilidade e precisão na lógica das suas consultas.

Os dados de resultados estão disponíveis nos seguintes campos:

  • Os valores de resultados mantêm os respetivos tipos originais no campo variables.
  • O campo outcomes armazena as versões string para retrocompatibilidade.

Pode aceder a estes valores de resultados através do mapa variables para obter o tipo específico ou aceder a elementos numa sequência através da indexação de matrizes. Pode aceder a um item específico na sequência pelo respetivo índice ou selecionar a sequência completa para avaliar cada valor individualmente.

Sintaxe:

$d.detection.detection.variables[OUTCOME_NAME].TYPE_SUFFIX

Sintaxe para sequências:

$d.detection.detection.variables[OUTCOME_NAME].SEQUENCE_TYPE_SUFFIX.TYPE_VALS_SUFFIX

Exemplos: aceda às variáveis de resultados nos mapas

Aceda a um resultado de string:

    $my_string_outcome = $d.detection.detection.variables["outcome_ip"].string_val
   

Este exemplo obtém o valor da string diretamente (por exemplo, "1.1.1.1" if outcome_ip era uma única string).

Aceda a um resultado de número inteiro

    $my_int_outcome = $d.detection.detection.variables["outcome_port"].int64_value
    

Este exemplo obtém o valor inteiro (por exemplo, 30).

Aceda a uma lista de números inteiros através de Int64Sequence

   $my_int_list = $d.detection.detection.variables["outcome_ports"].int64_seq.int64_vals
   

Este exemplo obtém a lista completa de números inteiros e anula a aninhagem dos mesmos, como campos repetidos (por exemplo, [2, 3, 4]).

Aceda a um elemento específico de uma lista de números inteiros

    $first_int = $d.detection.detection.variables["outcome_ports"].int64_seq.int64_vals[0]
    

Este exemplo obtém o primeiro número inteiro da lista (por exemplo, 2).

Aceda a uma lista de strings (StringSequence)

    $my_string_list = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals
    

Este exemplo obtém a lista completa de strings e anula a aninhagem das mesmas, como os campos repetidos (por exemplo, ["1.1.1.1", "2.2.2.2"]).

Aceda a um elemento específico a partir de uma lista de strings

    $first_ip = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals[0]
    

Este exemplo obtém o primeiro endereço IP da lista (por exemplo, "1.1.1.1").

Sufixos de tipo disponíveis para variables

Para ver uma lista completa dos sufixos suportados, consulte o artigo FindingVariable.

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