Visão geral da linguagem YARA-L 2.0

YARA-L 2.0 é uma linguagem de computador usada para criar regras para a pesquisa nos seus dados de registros corporativos conforme eles são ingeridos na sua conta do Chronicle. A sintaxe YARA-L é derivada da linguagem YARA desenvolvida pelo VirusTotal. A linguagem funciona com o Chronicle Detection Engine e permite pesquisar ameaças e outros eventos em grandes volumes de dados. Consulte também a sintaxe da linguagem YARA-L 2.0.

Estrutura da regra

Para YARA-L 2, você precisa especificar declarações, definições e usos de variáveis na seguinte ordem:

  1. meta
  2. events
  3. match (opcional)
  4. condição

Veja a seguir a estrutura genérica de uma regra:

rule <rule Name>
{
  meta:
    // Stores arbitrary key-value pairs of rule details, such as who wrote
    // it, what it detects on, version control, etc.
    // Identical to the meta section in YARA-L.
    //
    // For example:
    // author = "Analyst #2112"
    // date = "08/09/2020"
    // description = "suspicious domain detected"

  events:
    // Conditions to filter events and the relationship between events.

  match:
    // Values to return when matches are found.

  condition:
    // Condition to check events and the variables used to find matches.
}

Regras de exemplo do YARA-L 2.0

Os exemplos a seguir mostram as regras escritas em YARA-L 2.0. Cada um demonstra como correlacionar eventos dentro da linguagem da regra.

Logins de diferentes cidades

A regra a seguir busca usuários que fizeram login na sua empresa em duas ou mais cidades em menos de cinco minutos:

rule DifferentCityLogin {
  meta:

  events:
    $udm.metadata.event_type = "USER_LOGIN"
    $udm.principal.user.userid = $user
    $udm.principal.location.city = $city

  match:
    $user over 5m

  condition:
    #city > 1
}

Variável de correspondência: $user

Variável do evento:$udm

Variável do marcador: $city $user

Veja a seguir uma descrição de como essa regra funciona:

  • Agrupa eventos com o nome de usuário ($user) e o retorna ($user) quando uma correspondência é encontrada.
  • O período é de 5 minutos. Isso significa que apenas eventos com menos de 5 minutos de diferença são correlacionados.
  • Pesquisando um grupo de eventos ($udm) com o tipo de evento USER_LOGIN.
  • Para esse grupo de eventos, a regra chama o ID do usuário como $user e a cidade de login como $city.
  • Retorna uma correspondência se o número distinto de valores $city for maior que 1 no grupo de eventos ($udm) dentro do intervalo de 5 minutos.

Criação e exclusão rápidas de usuários

A regra a seguir busca usuários que foram criados e excluídos em quatro horas:

  rule UserCreationThenDeletion {
  meta:

  events:
    $create.target.user.userid = $user
    $create.metadata.event_type = "USER_CREATION"

    $delete.target.user.userid = $user
    $delete.metadata.event_type = "USER_DELETION"

    $create.metadata.event_timestamp.seconds <=
       $delete.metadata.event_timestamp.seconds

  match:
    $user over 4h

  condition:
    $create and $delete
}

Variáveis de evento:$create e $delete

Variável de correspondência: $user

Variável do marcador: N/A

Veja a seguir uma descrição de como essa regra funciona:

  • Agrupa eventos com o nome de usuário ($user) e o retorna ($user) quando uma correspondência é encontrada.
  • A janela de tempo é de quatro horas, o que significa que apenas eventos separados por menos de quatro horas estão correlacionados.
  • Pesquisa dois grupos de eventos ($create e $delete, em que $create é equivalente a #create >= 1).
  • $create corresponde a eventos USER_CREATION e chama o ID do usuário como $user.
  • $user é usado para unir os dois grupos de eventos.
  • $delete corresponde a eventos USER_DELETION e chama o ID do usuário como $user. Essa regra procura uma correspondência em que o identificador de usuário nos dois grupos de eventos seja o mesmo.
  • Esta regra procura casos em que o evento de $delete acontece depois do evento de $create, retornando uma correspondência quando descoberto.

Evento único x vários eventos

Os exemplos de regras a seguir mostram como criar uma regra para pesquisar um único evento e, em seguida, modificá-la para pesquisar vários eventos.

Esta é a única versão do evento da regra:

rule SingleEventRule {
  meta:
    author = "noone@altostrat.com"

  events:
    $e.metadata.event_type = "USER_LOGIN"

  condition:
    $e
}

Esta regra só procura um evento de login de usuário e retorna o primeiro evento encontrado nos dados corporativos armazenados na sua conta do Chronicle.

Esta é uma versão de vários eventos da regra:

rule MultiEventRule {
  meta:
    author = "noone@altostrat.com"

  events:
    $e.metadata.event_type = "USER_LOGIN"
    $e.principal.user.userid = $user

  match:
    $user over 10m

  condition:
    #e >= 10
}

A regra pesquisa um usuário que fez login pelo menos 10 vezes em menos de 10 minutos.

Evento único dentro do intervalo de endereços IP

O exemplo a seguir mostra uma única regra de evento que pesquisa uma correspondência entre dois usuários específicos e um intervalo específico de endereços IP:

rule OrsAndNetworkRange {
  meta:
    author = "noone@altostrat.com"

  events:
    // Checks CIDR ranges.
    net.ip_in_range_cidr($e.principal.ip, "203.0.113.0/24")

    // Detection when the hostname field matches either value using or.
    $e.principal.hostname = /pbateman/ or $e.principal.hostname = /sspade/

  condition:
    $e
}

Campos repetidos

Na YARA-L 2.0, os campos repetidos são representados como matrizes.

Por exemplo, um host pode ter vários endereços IP:

principal.ip [192.168.1.2, 10.3.4.100, 192.168.12.16]

Ou um endereço de e-mail pode ter vários destinatários:

network.email.to ["a@google.com", "b@google.com", "c@google.com"]

Sintaxe

Campos repetidos podem ser referidos da mesma maneira que campos não repetidos. Nesse caso, elas são automaticamente eliminadas, ou seja, as condições são comparadas com os elementos individuais do campo repetido.

Por exemplo, se você incluir a instrução a seguir em uma regra:

$e.principal.ip = "192.168.12.16"

O Chronicle procura um endereço IP dentro da matriz que corresponda a "192.168.12.16". Neste exemplo, um endereço correspondente seria encontrado e uma detecção seria retornada.

Por exemplo, se você incluir a instrução a seguir em uma regra:

$e.principal.ip = "192.168.12.16" and $e.principal.ip = "10.3.4.100"

O Chronicle procura um endereço IP dentro da matriz que corresponda a "192.168.12.16" e "10.3.4.100". Neste exemplo, nenhum endereço correspondente seria encontrado, e nenhuma detecção seria retornada.

Exemplo de campos repetidos

A regra a seguir procura eventos em que um endereço IP de origem se conectou a um endereço IP de destino enquanto faz solicitações a mais de 50 portas de destino diferentes em um período de menos de um minuto. Provavelmente é uma entidade mal-intencionada que procura uma porta de rede não segura.

rule RepeatedFieldsRuleExample {
  meta:
    author = "noone@google.com"

  events:
    $e.principal.ip = $source_ip
    $e.target.ip = $target_ip
    $e.target.port = $target_port

  match:
    $source_ip, $target_ip over 1m

  condition:
    #target_port > 50
}

todos os operadores

Os campos repetidos também podem ser referenciados com os operadores any e all. Nesse caso, elas não serão ambíguas, o que significa que as condições são verificadas em relação a todos os elementos do campo repetido.

Por exemplo, se você incluir a instrução a seguir em uma regra:

any $e.principal.ip = "192.168.12.16"

O Chronicle verifica se algum endereço IP dentro da matriz corresponde a "192.168.12.16". Neste exemplo, a matriz satisfaz a verificação e retorna uma detecção.

Se você incluir a seguinte instrução na regra:

all $e.principal.ip = "192.168.12.16"

O Chronicle verifica se todos os endereços IP dentro da matriz correspondem a "192.168.12.16". Neste exemplo, a matriz não atenderia à verificação e não retornaria uma detecção.

Se você incluir a seguinte instrução na regra:

any $e.principal.ip = "192.168.12.16" and any $e.principal.ip = "10.3.4.100"

O Chronicle verifica se algum endereço IP na matriz corresponde a "192.168.12.16" e se algum endereço IP dentro da matriz corresponde a "10.3.4.100". Neste exemplo, a matriz satisfaz a verificação e retorna uma detecção.

Veja a seguir exemplos de predicados válidos usando os operadores any e all:

  • any $e.principal.ip = "192.168.12.16"
  • net.ip_in_range_cidr(any $e.principal.ip, "192.168.12.16/24")
  • all $e.network.email.to = /.*@google\.com/
  • re.regex(all $e.network.email.to, `.*google\.com`)

Veja a seguir exemplos de predicados inválidos usando os operadores any e all:

  • any $ip = "192.168.12.16"
  • any $e.principal.ip = all $e.target.ip
  • any $e.principal.ip in %reference_list

Limitações de qualquer um dos operadores

Os operadores any e all só podem ser usados com campos repetidos. Além disso, não é possível usá-los ao atribuir um campo repetido a uma variável do marcador ou ao mesclar com um campo de outro evento.

Por exemplo, any $e.principal.ip = $ip e any $e1.principal.ip = $e2.principal.ip não são sintaxes válidas. Para fazer a correspondência ou participar de um campo repetido, use $e.principal.ip = $ip. Haverá um valor de variável de correspondência ou junção para cada elemento do campo repetido.

Ao gravar uma condição com any ou all, lembre-se de que negar a condição com not pode não ter o mesmo significado que usar o operador negado.

Exemplo:

  • not all $e.principal.ip = "192.168.12.16" verifica se nem todos os endereços IP correspondem a "192.168.12.16", o que significa que a regra está verificando se algum endereço IP não corresponde a "192.168.12.16".
  • all $e.principal.ip != "192.168.12.16" verifica se todos os endereços IP não correspondem a "192.168.12.16", o que significa que a regra está verificando se nenhum endereço IP corresponde a "192.168.12.16".

um exemplo de regra

A regra a seguir procura eventos de login em que todos os endereços IP de origem não correspondem a um endereço IP conhecido como seguro em um período de cinco minutos.

rule SuspiciousIPLogins {
  meta:
    author = "noone@google.com"

  events:
    $e.metadata.event_type = "USER_LOGIN"

    // Detects if all source IP addresses in an event do not match "100.97.16.0"
    // For example, if an event has source IP addresses
    // ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
    // it will be detected since "100.97.16.1", "100.97.16.2",
    // and "100.97.16.3" all do not match "100.97.16.0".

    all $e.principal.ip != "100.97.16.0"

    // Assigns placeholder variable $ip to the $e.principal.ip repeated field.
    // There will be one detection per source IP address.
    // For example, if an event has source IP addresses
    // ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
    // there will be one detection per address.

    $e.principal.ip = $ip

  match:
    $ip over 5m

  condition:
    $e
}

Expressões regulares em uma regra

O exemplo de expressão regular YARA-L 2.0 a seguir procura eventos com e-mails recebidos do domínio altostrat.com. Como nocase foi adicionada à comparação da variável $host regex e à função regex, ambas as comparações não diferenciam maiúsculas de minúsculas.

rule RegexRuleExample {
  meta:
    author = "noone@altostrat.com"

  events:
    $e.principal.hostname = $host
    $host = /.*HoSt.*/ nocase
    re.regex($e.network.email.from, `.*altostrat\.com`) nocase

  match:
    $host over 10m

  condition:
    #e > 10
}

Janelas deslizantes YARA-L

Por padrão, as regras YARA-L 2.0 são avaliadas usando janelas de salto. Um intervalo de tempo dos dados de eventos corporativos é dividido em um conjunto de janelas de salto sobrepostas, cada uma com a duração especificada na seção match. Os eventos são correlacionados em cada janela de salto. Com as janelas de salto, não é possível pesquisar eventos que acontecem em uma ordem específica, por exemplo, e1 acontece até 2 minutos depois de e2. Uma ocorrência do evento e1 e uma ocorrência do evento e2 são correlacionadas, desde que estejam dentro da duração da janela de salto.

As regras também podem ser avaliadas usando janelas deslizantes. As janelas deslizantes, com a duração especificada na seção match, são geradas ao começar ou terminar com uma variável de evento dinâmico especificada. Os eventos são correlacionados dentro de cada janela deslizante. Isso possibilita a pesquisa de eventos que ocorrem em uma ordem específica, por exemplo, e1 acontece dentro de dois minutos após e2. Uma ocorrência do evento e1 e uma ocorrência do evento e2 serão correlacionadas se o evento e1 ocorrer dentro da duração da janela variável depois do evento e2.

Sintaxe da regra da janela deslizante

Especifique as janelas deslizantes na seção de correspondência de uma regra da seguinte maneira:

<match-variable-name-1>, <match-variable-name-2>, ... over <sliding-window- duration> before|after <pivot-event-variable-name>

A variável de evento dinâmico é a variável de evento em que as janelas deslizantes são baseadas. Se você usar a palavra-chave before, serão geradas janelas deslizantes, terminando com cada ocorrência do evento dinâmico. Se a palavra-chave after for usada, as janelas deslizantes serão geradas a partir de cada ocorrência do evento dinâmico.

Exemplo de regra de janela deslizante

O exemplo de janela deslizante YARA-L 2.0 a seguir pesquisa a ausência de eventos firewall_2 após eventos firewall_1. A palavra-chave after é usada com a variável do evento dinâmico $e1 para especificar que apenas janelas de 10 minutos após cada evento firewall_1 precisam ser verificadas ao correlacionar eventos.

rule SlidingWindowRuleExample {
  meta:
    author = "noone@google.com"

  events:
    $e1.metadata.product_name = "firewall_1"
    $e1.principal.hostname = $host

    $e2.metadata.product_name = "firewall_2"
    $e2.principal.hostname = $host

  match:
    $host over 10m after $e1

  condition:
    $e1 and !$e2
}