Descripción general del lenguaje YARA-L 2.0

YARA-L 2.0 es un lenguaje de computación que se usa para crear reglas de búsqueda en los datos de registro de tu empresa a medida que se transfieren a tu instancia de Chronicle. La sintaxis YARA-L se deriva del lenguaje YARA que desarrolló VirusTotal. El lenguaje funciona en conjunto con Chronicle Detection Engine y te permite buscar amenazas y otros eventos en grandes volúmenes de datos.

Para obtener más información, consulta lo siguiente:

Reglas de ejemplo de YARA-L 2.0

En los siguientes ejemplos, se muestran reglas escritas en YARA-L 2.0. Cada uno demuestra cómo correlacionar eventos dentro del lenguaje de las reglas.

Reglas y ajuste

La siguiente regla busca patrones específicos en los datos de eventos y crea una detección si los encuentra. Esta regla incluye una variable $e1 para el tipo de evento de seguimiento y el campo metadata.event_type de UDM. La regla verifica si hay casos específicos de expresiones regulares que coincidan con e1. Cuando se lleva a cabo el evento $e1, se crea una detección. Se incluye una condición not en la regla para excluir determinadas rutas de acceso no maliciosas. Puedes agregar condiciones not para evitar los 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
}

Ingresos desde diferentes ciudades

La siguiente regla busca usuarios que hayan iniciado sesión en tu empresa desde dos o más ciudades en 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
}

Variable de coincidencia: $user

Variable del evento:$udm

Variable de marcador de posición: $city y $user

A continuación, se describe el funcionamiento de esta regla:

  • Agrupa los eventos con nombre de usuario ($user) y lo muestra ($user) cuando se encuentra una coincidencia.
  • El período es de 5 minutos, lo que significa que solo se correlacionan los eventos con menos de 5 minutos de diferencia.
  • Búsqueda de un grupo de eventos ($udm) cuyo tipo de evento es USER_LOGIN.
  • Para ese grupo de eventos, la regla llama al ID de usuario como $user y a la ciudad de acceso como $city..
  • Muestra una coincidencia si el número distinto de valores city (indicados por #city) es mayor que 1 en el grupo de eventos ($udm) dentro del intervalo de tiempo de 5 minutos.

Creación y eliminación rápidas de usuarios

La siguiente regla busca los usuarios que se crearon y, luego, se borraron en un plazo de 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
}

Variables del evento:$create y $delete

Variable de coincidencia: $user

Variable de marcador de posición: N/A

A continuación, se describe el funcionamiento de esta regla:

  • Agrupa los eventos con nombre de usuario ($user) y lo muestra ($user) cuando se encuentra una coincidencia.
  • La ventana de tiempo es de 4 horas, lo que significa que solo se correlacionan los eventos separados por menos de 4 horas.
  • Busca dos grupos de eventos ($create y $delete, donde $create equivale a #create >= 1).
  • $create corresponde a eventos USER_CREATION y llama al ID del usuario como $user.
  • $user se usa para unir los dos grupos de eventos.
  • $delete corresponde a eventos USER_DELETION y llama al ID del usuario como $user. Esta regla busca una coincidencia en la que el identificador de usuario en los dos grupos de eventos sea el mismo.
  • Esta regla busca casos en los que el evento de $delete ocurre después que el evento de $create y muestra una coincidencia cuando se descubre.

Regla de evento único

Las reglas de evento único se correlacionan sobre un evento único. Una única regla de evento puede ser:

  • Cualquier regla sin una sección que coincida.
  • Regla con una sección match y una sección condition que solo comprueba la existencia de 1 evento (por ejemplo, "$e", "#e > 0", "#e >= 1", "1 <= #e", "0 < #e").

Por ejemplo, la siguiente regla busca un evento de acceso de usuario y muestra el primero que encuentre en los datos empresariales almacenados en tu cuenta de Chronicle:

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

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

  condition:
    $e
}

Este es otro ejemplo de una sola regla de evento con una sección de coincidencia. Esta regla busca un usuario que haya accedido al menos una vez en menos de 5 minutos. Comprueba la existencia simple de un evento de acceso del usuario.

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
}

Regla de varios eventos

Usa varias reglas de eventos para agrupar muchos eventos durante un período específico y tratar de encontrar correlaciones entre eventos. Una regla típica de varios eventos tendrá lo siguiente:

  • Una sección match, que especifica el intervalo de tiempo durante el cual se deben agrupar los eventos
  • Una sección condition que especifica qué condición debe activar la detección y verifica la existencia de varios eventos

Por ejemplo, la siguiente regla busca un usuario que haya accedido al menos 10 veces en 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 del rango de direcciones IP

El siguiente ejemplo muestra una regla de evento única que busca una coincidencia entre dos usuarios específicos y un rango específico de direcciones 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
}

ejemplo de todas las reglas

La siguiente regla busca eventos de acceso en los que todas las direcciones IP de origen no coincidan con una dirección IP que se sabe que es segura en un 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
}

Expresiones regulares en una regla

En el siguiente ejemplo de expresión regular YARA-L 2.0, se buscan eventos con correos electrónicos recibidos del dominio altostrat.com. Dado que nocase se agregó a la comparación regex de la variable $host y a la función regex, estas comparaciones no distinguen entre mayúsculas y 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
}

Ejemplo de regla de ventana variable

En el siguiente ejemplo de ventana deslizante de YARA-L 2.0, se busca la ausencia de eventos firewall_2 después de eventos firewall_1. La palabra clave after se usa con la variable de evento dinámica $e1 para especificar que solo se deben verificar las ventanas de 10 minutos después de cada evento firewall_1 cuando se correlacionan los 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
}

Ejemplo de exclusión de valor cero

Rules Engine filtra de forma implícita los valores cero para todos los marcadores de posición que se usan en la sección match. Para obtener más información, consulta el manejo de valores cero en la sección match. Esto se puede inhabilitar con la opción allow_zero_values como se describe en allow_zero_values.

Sin embargo, para otros campos de evento a los que se hace referencia, no se excluyen valores cero, a menos que especifiques esas condiciones de forma explícita.

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
}

Ejemplo de regla con la sección outcome

Puedes agregar la sección outcome opcional a la regla YARA-L 2.0 para extraer información adicional de cada detección. En la sección de condiciones, también puedes especificar condicionales sobre las variables de resultados. Puedes usar la sección outcome de una regla de detección a fin de establecer variables para el consumo posterior. Por ejemplo, puedes configurar una puntuación de gravedad según los datos de los eventos que se analizan.

Para obtener más información, consulta lo siguiente:

Regla de varios eventos con sección de resultados:

La siguiente regla busca dos eventos para obtener el valor de $hostname. Si el valor de $hostname coincide durante un período de 5 minutos, se aplica una puntuación de gravedad. Cuando se incluye un período en la sección match, la regla se verifica dentro del 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")
}

Regla de un solo evento con sección 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
}

Refactorizar una regla de resultado de varios eventos en una regla de resultado de un solo evento

Puedes usar la sección outcome para reglas de un solo evento (reglas sin una sección match) y reglas de varios eventos (reglas con una sección match). Si antes diseñaste una regla para que sea multieventos solo para poder usar la sección de resultados, puedes refactorizar de manera opcional esas reglas si borras la sección match para mejorar el rendimiento. Ten en cuenta que, debido a que la regla ya no tiene una sección match que aplica la agrupación, es posible que recibas más detecciones. Esta refactorización solo es posible para reglas que usan una variable de evento, como se muestra en el siguiente ejemplo.

Regla de resultados de varios eventos que usa solo una variable de evento (un buen candidato para una refactorización):

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
}

Puedes refactorizar la regla si borras la sección match. Ten en cuenta que también debes quitar el agregado en la sección outcome, ya que la regla ahora será de un solo evento. Para obtener más información sobre las agregaciones, consulta agregaciones 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
}

Ejemplo de una función a una regla de marcador de posición

Puedes asignar una variable de marcador de posición al resultado de una llamada a función y usarla en otras secciones de la regla, como las secciones match, outcome o condition. Consulta el siguiente ejemplo:

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
}

Regla de ejemplo de condicionales de resultados

En la sección condition, puedes usar variables de resultado que se definieron en la sección outcome. En el siguiente ejemplo, se muestra cómo filtrar las puntuaciones de riesgo para reducir el ruido en las detecciones mediante condicionales 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
}