Visão geral da linguagem YARA-L 2.0

Compatível com:

A YARA-L 2.0 é uma linguagem de computador usada para criar regras de pesquisa nos dados de registro da empresa conforme eles são ingeridos na sua instância de Operações de segurança do Google. A sintaxe YARA-L é derivada da linguagem YARA desenvolvida pelo VirusTotal. A linguagem funciona em conjunto com o Google Security Operations Detection Engine e permite procurar ameaças e outros eventos em grandes volumes de dados.

Para ver mais informações, consulte os seguintes tópicos:

Regras de exemplo da YARA-L 2.0

Os exemplos a seguir mostram regras escritas em YARA-L 2.0. Cada um demonstra como correlacionar eventos na linguagem de regras.

Regras e ajustes

A regra a seguir verifica padrões específicos em dados de eventos e cria uma detecção se encontrar os padrões. Esta regra inclui uma variável $e1 para rastrear eventos de usuário e campo de UDM metadata.event_type. A regra verifica ocorrências específicas de correspondências de expressões regulares com e1. Quando o evento $e1 ocorre, uma detecção é criada. Uma condição not está incluída na regra para excluir determinados caminhos não maliciosos. Você pode adicionar condições not para evitar falsos positivos.

rule suspicious_unusual_location_svchost_execution
{

 meta:
   author = "Google Cloud Security"
   description = "Windows 'svchost' executed from an unusual location"
   yara_version = "YL2.0"
   rule_version = "1.0"

 events:

   $e1.metadata.event_type = "PROCESS_LAUNCH"
   re.regex($e1.principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
   not re.regex($e1.principal.process.command_line, `\\Windows\\System32\\`) nocase

condition:

   $e1
}

Logins de diferentes cidades

A regra a seguir procura usuários que tenham feito login em sua empresa em duas ou mais cidades em menos de 5 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:
    $udm and #city > 1
}

Variável de correspondência: $user

Variável de evento:$udm

Variável do marcador de posição: $city e $user

Veja a seguir como essa regra funciona:

  • Agrupa eventos com o nome de usuário ($user) e o retorna ($user) quando uma correspondência é encontrada.
  • O intervalo de tempo é de 5 minutos, o que significa que apenas eventos com menos de 5 minutos de diferença são correlacionados.
  • Pesquisando um grupo de eventos ($udm) cujo 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 (indicado por #city) for maior que 1 no grupo de eventos ($udm) no intervalo de cinco minutos.

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

A regra a seguir pesquisa usuários que foram criados e excluídos em até 4 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 de posição: N/A

Veja a seguir 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 4 horas, ou seja, apenas eventos com intervalos de menos de 4 horas são correlacionados.
  • Pesquisa dois grupos de eventos ($create e $delete, em que $create é equivalente a #create >= 1).
  • $create corresponde aos 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 do usuário nos dois grupos de eventos é o mesmo.
  • Esta regra procura casos em que o evento de $delete acontece depois do evento de $create, retornando uma correspondência quando descoberto.

Regra de evento único

As regras de eventos únicos são regras que se correlacionam com um único evento. Uma única regra de evento pode ser:

  • Qualquer regra sem uma seção de correspondência.
  • Regra com uma seção match e uma condition que verifica apenas a existência de um evento (por exemplo, "$e", "#e > 0", "#e >= 1", "1 <= #e", "0 < #e").

Por exemplo, a regra a seguir procura um evento de login do usuário e retorna o primeiro que encontrar nos dados corporativos armazenados na sua conta do Google Security Operations:

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

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

  condition:
    $e
}

Confira outro exemplo de uma regra de evento único com uma seção de correspondência. Esta regra procura um usuário que tenha feito login pelo menos uma vez em menos de 5 minutos. Ele verifica a existência simples de um evento de login de usuário.

rule SingleEventRule {
  meta:
    author = "alice@example.com"
    description = "windowed single event example rule"

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

  match:
    $user over 5m

  condition:
    #e > 0
}
rule MultiEventRule{
  meta:
    author = "alice@example.com"
    description = "Rule with outcome condition and simple existence condition on one event variable"

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

  match:
    $user over 10m

  outcome:
    $num_events_in_match_window = count($e.metadata.id)

  condition:
    #e > 0 and $num_events_in_match_window >= 10 // Could be rewritten as #e >= 10
}

Regra de vários eventos

Usar várias regras de eventos para agrupar diversos eventos em um período específico e tentar encontrar correlações entre os eventos. Uma regra típica de vários eventos terá o seguinte:

  • Uma seção match que especifica o período em que os eventos precisam ser agrupados.
  • Uma seção condition especificando qual condição acionará a detecção e verifique a existência de vários eventos.

Por exemplo, a regra a seguir procura um usuário que fez login pelo menos 10 vezes em menos de 10 minutos:

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
}

Evento único dentro do intervalo de endereços IP

O exemplo a seguir mostra uma única regra de evento pesquisando 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
}

exemplo de regra "todos"

A regra a seguir pesquisa eventos de login em que todos os endereços IP de origem não correspondem a um endereço IP conhecido por ser seguro em um período de 5 minutos.

rule SuspiciousIPLogins {
  meta:
    author = "alice@example.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 da YARA-L 2.0 a seguir pesquisa eventos com e-mails recebidos do domínio altostrat.com. Como nocase foi adicionado à comparação regex da variável $host e à função regex, essas 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
}

Exemplo de regra de janela deslizante

O exemplo de janela deslizante da YARA-L 2.0 a seguir procura a ausência de Eventos firewall_2 após firewall_1. A palavra-chave after é usada com a variável de evento de pivô $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 = "alice@example.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
}

Exemplo de exclusão de valor zero

O Mecanismo de regras filtra implicitamente os valores zero para todos os marcadores de posição que são usados na seção match. Para mais informações, consulte Processamento de valores zero na seção match. Essa opção pode ser desativada usando a opção allow_zero_values como descritos em allow_zero_values.

No entanto, para outros campos de evento referenciados, valores zero não são excluídos, a menos que você especifique explicitamente essas condições.

rule ExcludeZeroValues {
  meta:
    author = "alice@example.com"

  events:
    $e1.metadata.event_type = "NETWORK_DNS"
    $e1.principal.hostname = $hostname

    // $e1.principal.user.userid may be empty string.
    $e1.principal.user.userid != "Guest"

    $e2.metadata.event_type = "NETWORK_HTTP"
    $e2.principal.hostname = $hostname

    // $e2.target.asset_id cannot be empty string as explicitly specified.
    $e2.target.asset_id != ""

  match:
    // $hostname cannot be empty string. The rule behaves as if the
    // predicate, `$hostname != ""` was added to the events section, because
    // `$hostname` is used in the match section.
    $hostname over 1h

  condition:
    $e1 and $e2
}

Exemplo de regra com outcome seção

É possível adicionar a seção outcome opcional na regra YARA-L 2.0 para extrair informações adicionais de cada detecção. Na seção "Condição", também é possível especificar condicionais às variáveis de resultado. É possível usar a seção outcome de uma para definir variáveis de consumo downstream. Por exemplo, você pode definir pontuação de gravidade com base nos dados dos eventos que estão sendo analisados.

Para ver mais informações, consulte os seguintes tópicos:

Regra de vários eventos com seção de resultado:

A regra a seguir analisa dois eventos para obter o valor de $hostname: Se o valor de $hostname corresponder a um período de cinco minutos, uma pontuação de gravidade é aplicada. Ao incluir um período na seção match, as verificações de regras no período especificado.

rule OutcomeRuleMultiEvent {
    meta:
      author = "Google Cloud Security"
    events:
      $u.udm.principal.hostname = $hostname
      $asset_context.graph.entity.hostname = $hostname

      $severity = $asset_context.graph.entity.asset.vulnerabilities.severity

    match:
      $hostname over 5m

    outcome:
      $risk_score =
        max(
            100
          + if($hostname = "my-hostname", 100, 50)
          + if($severity = "HIGH", 10)
          + if($severity = "MEDIUM", 5)
          + if($severity = "LOW", 1)
        )

      $asset_id_list =
        array(
          if($u.principal.asset_id = "",
             "Empty asset id",
             $u.principal.asset_id
          )
        )

      $asset_id_distinct_list = array_distinct($u.principal.asset_id)

      $asset_id_count = count($u.principal.asset_id)

      $asset_id_distinct_count = count_distinct($u.principal.asset_id)

    condition:
      $u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}

rule OutcomeRuleMultiEvent {
    meta:
      author = "alice@example.com"
    events:
      $u.udm.principal.hostname = $hostname
      $asset_context.graph.entity.hostname = $hostname

      $severity = $asset_context.graph.entity.asset.vulnerabilities.severity

    match:
      $hostname over 5m

    outcome:
      $total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)

      $risk_score = if(total_network_bytes > 1024, 100, 50) + 
        max(
          if($severity = "HIGH", 10)
          + if($severity = "MEDIUM", 5)
          + if($severity = "LOW", 1)
        )

      $asset_id_list =
        array(
          if($u.principal.asset_id = "",
             "Empty asset id",
             $u.principal.asset_id
          )
        )

      $asset_id_distinct_list = array_distinct($u.principal.asset_id)

      $asset_id_count = count($u.principal.asset_id)

      $asset_id_distinct_count = count_distinct($u.principal.asset_id)

    condition:
      $u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}

Regra de evento único com seção de resultados:

rule OutcomeRuleSingleEvent {
    meta:
        author = "alice@example.com"
    events:
        $u.metadata.event_type = "FILE_COPY"
        $u.principal.file.size = $file_size
        $u.principal.hostname = $hostname

    outcome:
        $suspicious_host = $hostname
        $admin_severity = if($u.principal.userid in %admin_users, "SEVERE", "MODERATE")
        $severity_tag = if($file_size > 1024, $admin_severity, "LOW")

    condition:
        $u
}

Refatorar uma regra de resultado de vários eventos em uma regra de resultado de evento único.

Você pode usar a seção outcome para as duas regras de evento único (regras sem um seção match) e regras de vários eventos (regras com uma seção match). Se você já tiver criado uma regra como multieventos, use a seção de resultados, refatore essas regras excluindo a seção match para melhorar o desempenho. Como sua regra não tem mais uma seção match que aplica agrupamento, poderá receber mais detecções. Essa refatoração é possível para regras que usam uma variável de evento, conforme mostrado no exemplo a seguir.

A regra de resultado de vários eventos que usa apenas uma variável de evento (uma bom candidato para uma refatoração):

rule OutcomeMultiEventPreRefactor {
    meta:
      author = "alice@example.com"
      description = "Outcome refactor rule, before the refactor"

    events:
      $u.udm.principal.hostname = $hostname

    match:
      $hostname over 5m

    outcome:
      $risk_score = max(if($hostname = "my-hostname", 100, 50))

    condition:
      $u
}

É possível refatorar a regra excluindo a seção match. Observe que você também deve remover o agregado na seção outcome, já que a regra agora será em um único evento. Para mais informações sobre agregações, consulte agregações de resultados.

rule OutcomeSingleEventPostRefactor {
    meta:
      author = "alice@example.com"
      description = "Outcome refactor rule, after the refactor"

    events:
      $u.udm.principal.hostname = $hostname

    // We deleted the match section.

    outcome:
      // We removed the max() aggregate.
      $risk_score = if($hostname = "my-hostname", 100, 50)

    condition:
      $u
}

Exemplo de regra de função para marcador de posição

Você pode atribuir uma variável de espaço reservado ao resultado de uma chamada de função e pode usar a variável de marcador em outras seções da regra, como Seção match, outcome ou condition. Veja o exemplo a seguir:

rule FunctionToPlaceholderRule {
    meta:
      author = "alice@example.com"
      description = "Rule that uses function to placeholder assignments"

    events:
        $u.metadata.event_type = "EMAIL_TRANSACTION"

        // Use function-placeholder assignment to extract the
        // address from an email.
        // address@website.com -> address
        $email_to_address_only = re.capture($u.network.email.from , "(.*)@")

        // Use function-placeholder assignment to normalize an email:
        // uid@??? -> uid@company.com
        $email_from_normalized = strings.concat(
            re.capture($u.network.email.from , "(.*)@"),
            "@company.com"
        )

        // Use function-placeholder assignment to get the day of the week of the event.
        // 1 = Sunday, 7 = Saturday.
        $dayofweek = timestamp.get_day_of_week($u.metadata.event_timestamp.seconds)

    match:
        // Use placeholder (from function-placeholder assignment) in match section.
        // Group by the normalized from email, and expose it in the detection.
        $email_from_normalized over 5m

    outcome:
        // Use placeholder (from function-placeholder assignment) in outcome section.
        // Assign more risk if the event happened on weekend.
        $risk_score = max(
            if($dayofweek = 1, 10, 0) +
            if($dayofweek = 7, 10, 0)
        )

    condition:
        // Use placeholder (from function-placeholder assignment) in condition section.
        // Match if an email was sent to multiple addresses.
        #email_to_address_only > 1
}

Regra de exemplo de condicionais de resultado

Na seção condition, é possível usar variáveis de resultado que foram definidas na seção outcome. O exemplo a seguir demonstra como filtrar pontuações de risco para reduzir o ruído nas detecções usando condicionais de resultado.

rule OutcomeConditionalRule {
    meta:
        author = "alice@example.com"
        description = "Rule that uses outcome conditionals"

    events:
        $u.metadata.event_type = "FILE_COPY"
        $u.principal.file.size = $file_size
        $u.principal.hostname = $hostname

        // 1 = Sunday, 7 = Saturday.
        $dayofweek = timestamp.get_day_of_week($u.metadata.collected_timestamp.seconds)

    outcome:
        $risk_score =
            if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
            if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
            if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
            if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices

    condition:
        $u and $risk_score >= 10
}