Expresiones, operadores y otras construcciones

Se admite en los siguientes sistemas operativos:

En este documento, se incluye información para ayudarte a crear reglas y consultas de YARA-L con expresiones.

Expresiones booleanas

Las expresiones booleanas son expresiones con un tipo booleano, que incluye expresiones de comparación, expresiones de función y expresiones de lista de referencia o de tabla de datos. Puedes usar expresiones booleanas en las secciones events y outcome de una regla o consulta de YARA-L.

Expresiones de comparación

Las expresiones de comparación son expresiones que aplican un operador de comparación a dos expresiones. Las expresiones pueden ser campos de eventos, variables, literales o expresiones de funciones.

Ejemplo: Expresiones de comparación

$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")

Expresiones de función

Algunas expresiones de función devuelven un valor booleano, que se puede usar como un predicado individual en la sección events, como en el siguiente ejemplo:

re.regex()

net.ip_in_range_cidr()

Ejemplo: Expresiones de función

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

Lista de referencias o tabla de datos

Puedes usar listas de referencia o tablas de datos en las secciones events o outcome. Consulta Listas de referencia y Usa tablas de datos para obtener más información sobre el comportamiento y la sintaxis de las listas de referencia y las tablas de datos.

Ejemplo: Sintaxis para listas de referencia

En los siguientes ejemplos, se muestra la sintaxis para varios tipos de listas de referencia en una búsqueda:

// 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

Ejemplo: Sintaxis para tablas de datos

// 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

Ejemplo: Usa not y nocase en la sintaxis de las listas de referencia

// 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

El operador nocase es compatible con las listas STRING y REGEX.

Por motivos de rendimiento, el uso de listas de referencia y tablas de datos tiene las siguientes limitaciones:

  • Cantidad máxima de instrucciones in en una consulta, con o sin operadores especiales: 7
  • Cantidad máxima de sentencias in con el operador regex: 4
  • Cantidad máxima de sentencias in con el operador cidr: 2

Expresiones lógicas

Puedes usar los operadores lógicos and y or en la sección events.

Ejemplo: Expresiones 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"

De forma predeterminada, el orden de prioridad de mayor a menor es not, and y or. Por ejemplo, "a or b and c" se evalúa como "a or (b and c)" cuando los operadores or y and se definen de forma explícita en la expresión.

En la sección events, los predicados se unen con el operador and si no se define un operador de forma explícita. El orden de evaluación puede ser diferente si el operador and está implícito en la expresión. Considera las siguientes expresiones de comparación en las que or se define de forma explícita y el operador and está implícito.

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

Se interpreta de la siguiente manera:

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

Como or se define de forma explícita, los predicados circundantes se agrupan y evalúan primero. Es el último predicado, $e2.field = "bar". se une de forma implícita con and. El resultado es que cambia el orden de evaluación.

Tipos enumerados

Puedes usar los operadores con tipos enumerados. Se puede aplicar a las reglas para simplificar y optimizar el rendimiento (usar operadores en lugar de listas de referencia).

En el siguiente ejemplo, "USER_UNCATEGORIZED" y "USER_RESOURCE_DELETION" corresponden a 15000 y 15014, por lo que la regla buscará todos los eventos enumerados:

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

Modificador nocase

Para ignorar el uso de mayúsculas en una expresión de comparación entre valores de cadena o una expresión regular, agrega nocase al final de la expresión, como se muestra en los siguientes ejemplos.

Ejemplo: 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

El modificador nocase no se puede usar cuando el tipo de campo es un valor enumerado. Los siguientes ejemplos no son válidos y generarán errores de compilación:

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

Comentarios

Los comentarios se pueden usar en las consultas para proporcionar más información. Usas el carácter de barra diagonal para indicar un comentario:

  • Para un comentario de una sola línea, usa dos barras diagonales (// comment).
  • Para un comentario de varias líneas, usa el carácter de barra diagonal y el carácter de asterisco (/* comment */).

Literales

YARA-L admite números enteros y de punto flotante no negativos, cadenas, valores booleanos y literales de expresiones regulares. Los literales son valores fijos que se usan en las condiciones de las consultas. YARA-L también usa otras construcciones similares a literales, como expresiones regulares (encerradas entre barras diagonales) para la coincidencia de patrones y booleanos (verdadero/falso) para la lógica.

Literales de cadena

Los literales de cadena son secuencias de caracteres entre comillas dobles (") o comillas inversas (`). La cadena se interpreta de manera diferente según el tipo de comillas que uses:

  • Comillas dobles ("hola\tmundo"): Se usan para cadenas normales. Se deben incluir caracteres de escape, en los que \t se interpreta como una tabulación.
  • Comillas inversas (“hello\tworld”): Se usan cuando todos los caracteres se deben interpretar de forma literal, en cuyo caso \t no se interpreta como una tabulación.

Literales de expresiones regulares

Para los literales de expresiones regulares, tienes dos opciones:

  • Si deseas usar expresiones regulares directamente sin la función re.regex(), usa /regex/ para los literales de expresión regular.

  • Si quieres usar literales de cadena como literales de expresión regular, usa la función re.regex(). Ten en cuenta que, para los literales de cadena entre comillas dobles, debes escapar los caracteres de barra inversa con caracteres de barra inversa, lo que puede parecer extraño.

En los siguientes ejemplos, se muestran expresiones regulares equivalentes:

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

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

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

Google recomienda usar caracteres de comillas inversas para las cadenas en expresiones regulares para facilitar la lectura.

Operadores

Operador Descripción
= equal/declaration
!= no es igual
< menor que
<= menor o igual que
> mayor que
>= mayor o igual que

Variables

En YARA-L, todas las variables usan la sintaxis $<variable name>. En YARA-L, se pueden usar los siguientes tipos de variables.

Variables de evento

Las variables de eventos representan grupos de eventos o eventos de entidades. Puedes especificar condiciones para las variables de eventos en la sección events con un nombre, una fuente de eventos y campos de eventos.

  • Las fuentes de eventos son udm (para eventos normalizados) y graph (para eventos de entidades). Si se omite la fuente, se establece udm como la fuente predeterminada.

  • Los campos de eventos se representan como una cadena de .<nombre de campo> (por ejemplo, $e.field1.field2), y las cadenas de campos siempre comienzan desde la fuente de nivel superior (UDM o entidad).

Variables de coincidencia

Las variables de coincidencia se usan en la sección match para agrupar eventos según valores comunes dentro de un período especificado.

Se convierten en campos de agrupación para la consulta, ya que se devuelve una fila para cada conjunto único de variables de coincidencia (y para cada período). Cuando la búsqueda encuentra una coincidencia, se devuelven los valores de las variables de coincidencia.

En la sección events, especificas qué representa cada variable de coincidencia.

Variables de marcador de posición

Las variables de marcador de posición se usan para capturar y almacenar valores específicos de los campos de eventos del UDM, a los que se hace referencia y que se usan en toda la consulta. Se usan para vincular eventos dispares, especialmente en consultas con varios eventos. Si asignas un valor común (por ejemplo, userid o hostname) a un marcador de posición, puedes usarlo en la sección match para agrupar los eventos que comparten ese valor dentro de un período especificado.

Para definir variables de marcador de posición en la sección events, asigna el valor de un campo del UDM a un nombre de variable con el prefijo $ (por ejemplo, $targetUser = $e.target.user.userid).

También puedes definir variables de marcador de posición en las siguientes secciones:

  • Sección condition para especificar las condiciones de coincidencia
  • Sección outcome para realizar cálculos, definir métricas o extraer datos específicos de los eventos coincidentes
  • sección match para agrupar eventos por valores comunes.

Palabras clave

En YARA-L, las palabras clave son palabras reservadas que definen la estructura y la lógica de una consulta de detección. Se usan para especificar diferentes secciones de una búsqueda, realizar operaciones lógicas y matemáticas, y definir condiciones para que coincidan los eventos. Estas palabras clave no se pueden usar como identificadores para consultas, cadenas o variables.

Las palabras clave no distinguen entre mayúsculas y minúsculas (por ejemplo, and y AND son equivalentes).

Categorías clave de palabras clave de YARA-L 2.0

Esta lista no es exhaustiva, pero abarca las palabras clave principales que se usan en YARA-L 2.0 para crear consultas de detección sólidas.

  • Definición de la búsqueda:
    • rule: Inicia la definición de una nueva consulta de YARA-L.
    • private: Designa una búsqueda como privada, lo que impide que se exponga o active directamente de forma externa.
    • global: Marca una búsqueda como global, lo que indica que se debe aplicar de forma general.
  • Secciones de la búsqueda:
    • meta: Introduce la sección de metadatos para obtener información descriptiva sobre la búsqueda.
    • strings: Denota la sección en la que se definen los patrones de cadenas.
    • condition: Especifica la sección que contiene la lógica booleana para activar la búsqueda.
    • events: Define la sección para especificar las variables del evento y sus condiciones.
    • match: Presenta la sección para agregar valores en un período.
    • outcome: Define la sección para agregar contexto y puntuación a las búsquedas activadas.
  • Modificadores de cadenas:
    • ascii: Especifica que una cadena debe coincidir como texto ASCII.
    • wide: Indica que una cadena debe coincidir con caracteres anchos (UTF-16).
    • nocase: Realiza una coincidencia de cadena sin distinción entre mayúsculas y minúsculas.
    • fullword: Requiere que la cadena coincida como una palabra completa.
    • xor: Aplica la transformación XOR a la cadena antes de la coincidencia.
    • base64, base64wide: Aplica la codificación Base64 antes de la coincidencia.
  • Operadores lógicos:
    • and, or, not: Operadores lógicos booleanos estándar para combinar condiciones.
    • all of, any of: Se usan para evaluar varias expresiones dentro de una condición.
  • Operadores de comparación y relacionales:
    • at: Especifica un desplazamiento exacto para la coincidencia de cadenas.
    • contains: Comprueba si una cadena contiene una subcadena.
    • startswith, endswith: Comprueba si una cadena comienza o termina con una subcadena.
    • icontains, istartswith, iendswith, iequals: Son versiones que no distinguen mayúsculas de minúsculas.
    • matches: Se usa para la coincidencia de expresiones regulares.
  • Tipos de datos y especificadores de tamaño:
    • int8, uint8, int16, uint16, int32, uint32: Son tipos de números enteros con tamaños especificados.
    • int8be, uint8be, int16be, uint16be, int32be, uint32be: Versiones big-endian de tipos de números enteros.
    • filesize: Representa el tamaño del archivo que se analiza.
    • entrypoint: Hace referencia al punto de entrada de un archivo ejecutable.

Maps

YARA-L admite mapas para los tipos de datos Struct y Label, que se usan en algunos campos del UDM.

Para buscar un par clave-valor específico en los tipos de datos Struct y Label, usa la sintaxis de mapa estándar:

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

Ejemplo: Uso válido y no válido de mapas

En los siguientes ejemplos, se muestra el uso válido y no válido de los mapas.

Uso válido de mapas

Cómo usar un campo Struct en la sección de eventos:

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

Cómo usar un campo de etiqueta en la sección de resultados:

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

Cómo asignar un valor de mapa a un marcador de posición:

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

Cómo usar un campo de mapa en una condición de unión:

// 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"]

Uso no admitido de mapas

Combinación de palabras clave de any o all con un mapa

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

Otros tipos de valores

La sintaxis de mapa solo puede devolver un valor de cadena. En el caso de los tipos de datos [Struct](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#struct), la sintaxis de mapa solo puede acceder a las claves cuyos valores son cadenas. No es posible acceder a claves cuyos valores son otros tipos primitivos, como números enteros.

Manejo de valores duplicados en mapas

El acceso al mapa está diseñado para recuperar un solo valor asociado con una clave específica. Este es el comportamiento estándar y esperado. Sin embargo, en situaciones poco comunes, el contexto de map access podría apuntar inadvertidamente a varios valores. En el caso extremo poco común en el que el acceso al mapa hace referencia a varios valores, map access devolverá de forma determinística el primer valor. Esto puede ocurrir si una etiqueta tiene una clave duplicada o un campo repetido de elemento superior.

La etiqueta tiene una clave duplicada

La estructura de la etiqueta representa un mapa, pero no aplica la unicidad de la clave. Por convención, un mapa debe tener claves únicas, por lo que Google SecOps no recomienda completar una etiqueta con claves duplicadas.

Ejemplo: Etiqueta con clave duplicada

El texto de la búsqueda $e.metadata.ingestion_labels["dupe-key"] devolvería el primer valor posible, val1, si se ejecutara en el siguiente ejemplo de datos:

    // 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"
        }
      }
    }
  

La etiqueta tiene un campo repetido de elemento superior

Un campo repetido puede contener una etiqueta como campo secundario. Dos entradas diferentes en el campo repetido de nivel superior pueden contener etiquetas que tengan la misma clave.

Ejemplo: Etiqueta con campo repetido de elemento superior

El texto de la consulta $e.security_result.rule_labels["key"] devolvería el primer valor posible, "val3", si se ejecutara en el siguiente ejemplo de datos:

    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"
        }
      }
    }
  

Cómo acceder a las variables de resultado en los mapas

En esta sección, se explica cómo acceder a las variables de resultado dentro de los mapas como sus tipos de datos originales (por ejemplo, números enteros, booleanos o listas de estos tipos) en lugar de solo cadenas. Puedes usar esta funcionalidad para tener más flexibilidad y precisión en la lógica de tus consultas.

Los datos de resultados están disponibles en los siguientes campos:

  • Los valores de resultado conservan sus tipos originales en el campo variables.
  • El campo outcomes almacena versiones de string para la retrocompatibilidad.

Puedes acceder a estos valores de resultado con el mapa variables para recuperar el tipo específico o acceder a los elementos en una secuencia con la indexación de arrays. Puedes acceder a un elemento específico de la secuencia por su índice o seleccionar toda la secuencia para evaluar cada valor de forma individual.

Sintaxis:

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

Sintaxis para secuencias:

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

Ejemplos: Cómo acceder a las variables de resultado en los mapas

Accede a un resultado de cadena:

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

En este ejemplo, se recupera el valor de cadena directamente (por ejemplo, "1.1.1.1" si outcome_ip era una sola cadena).

Cómo acceder a un resultado de número entero

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

En este ejemplo, se recupera el valor entero (por ejemplo, 30).

Cómo acceder a una lista de números enteros con Int64Sequence

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

En este ejemplo, se recupera la lista completa de números enteros y se anula su anidamiento como campos repetidos (por ejemplo, [2, 3, 4]).

Cómo acceder a un elemento específico de una lista de números enteros

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

En este ejemplo, se recupera el primer número entero de la lista (por ejemplo, 2).

Cómo acceder a una lista de cadenas (StringSequence)

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

En este ejemplo, se recupera la lista completa de cadenas y se anula su anidamiento como campos repetidos (por ejemplo, ["1.1.1.1", "2.2.2.2"]).

Cómo acceder a un elemento específico de una lista de cadenas

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

En este ejemplo, se recupera la primera dirección IP de la lista (por ejemplo, "1.1.1.1").

Sufijos de tipo disponibles para variables

Para obtener una lista completa de los sufijos admitidos, consulta FindingVariable.

¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.