Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Sintaxis del lenguaje YARA-L 2.0

En esta sección, se describen los elementos principales de la sintaxis YARA-L. Consulta también Descripción general del lenguaje YARA-L 2.0.

Estructura de reglas

Para YARA-L 2.0, debes especificar las declaraciones de variables, definiciones y usos en el siguiente orden:

  1. meta
  2. eventos
  3. coincidencia (opcional)
  4. resultado (opcional)
  5. condición
  6. Opciones (opcional)

A continuación, se muestra la estructura genérica de una norma:

rule <rule Name>
{
  meta:
    // Stores arbitrary key-value pairs of rule details, such as who wrote
    // it, what it detects on, version control, etc.

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

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

  outcome:
    // Additional information extracted from each detection.

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

  options:
    // Options to turn on or off while executing this rule.
}

Comentarios

Designa los comentarios con dos caracteres de barra diagonal (// comment) o comentarios de varias líneas activados con asteriscos de barra (/* comment */), como lo harías en C.

Literales

Se admiten números enteros no negativos (sin puntos decimales), string, booleano y literales de regex.

Literales de string y regex

Puedes usar cualquiera de los siguientes caracteres de comillas para encerrar strings en YARA-L 2.0. Sin embargo, el texto citado se interpreta de manera diferente según el que uses.

  1. Comillas dobles ("), — para cadenas normales. Debe incluir caracteres de escape.
    Por ejemplo: “hello\tworld”:\t se interpreta como una pestaña

  2. Comillas inversas (`): úsalas para interpretar todos los caracteres literalmente.
    Por ejemplo: “hello\tworld”: \t no se interpreta como una pestaña

Para expresiones regulares, tienes dos opciones.

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

También puedes usar literales de string como literales de regex cuando usas la función re.regex(). Ten en cuenta que, para los literales de string de comillas dobles, se deben escapar los caracteres de la barra invertida con caracteres de barra invertida, que pueden resultar incómodos.

Por ejemplo, las siguientes expresiones regulares son 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 strings en expresiones regulares a fin de facilitar la legibilidad.

Operadores

Puedes usar los siguientes operadores en YARA-L:

Operador Descripción
= igual/declaración
!= no igual
< menor que
<= menor o igual que
> mayor que
>= mayor o igual que

Variables

En YARA-L 2.0, todas las variables se representan como $<variable name>.

Puedes definir los siguientes tipos de variables:

  • Variables de evento: representan grupos de eventos de forma normalizada (UDM) o eventos de entidades. Especifica las condiciones para las variables de evento en la sección events. Las variables de evento se identifican con un nombre, una fuente de evento y campos de evento. Las fuentes permitidas son udm (para eventos normalizados) y graph (para eventos de entidad). Si se omite la fuente, udm se establece como la fuente predeterminada. Los campos de eventos se representan como una cadena de .<field name> (por ejemplo, $e.field1.field2). Las cadenas de campos de eventos siempre comienzan desde la fuente de nivel superior (UDM o entidad).

  • Variables de coincidencia: Declara en la sección match. Las variables de coincidencia se convierten en campos de agrupación para la consulta, ya que se muestra una fila por cada conjunto único de variables de coincidencia (y para cada período). Cuando la regla encuentra una coincidencia, se muestran los valores de las variables de coincidencia. Especifica qué representa cada variable de coincidencia en la sección events.

  • Variables del marcador de posición: Declara y define en la sección events. Las variables de marcador de posición son similares a las variables de coincidencia. Sin embargo, puedes usar variables de marcador de posición en la sección condition para especificar las condiciones de coincidencia.

.

Usa variables de coincidencia y variables de marcador de posición para declarar relaciones entre campos de evento a través de condiciones de unión transitivas (consulta Sintaxis de la sección Eventos para obtener más detalles).

Maps

Estructuras y etiquetas

Algunos campos de UDM usan los tipos de datos Struct o Label.

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

// A Struct field.
$e.udm.additional.fields["pod_name"] = "kube-scheduler"
// A Label field.
$e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"

Casos admitidos

Sección de eventos y resultados
// Using a Struct field in the events section
events:
  $e.udm.additional.fields["pod_name"] = "kube-scheduler"

// Using a Label field in the outcome section
outcome:
  $value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])
Asignación de un valor de mapa a un marcador de posición
$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]
Usa 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"]

Casos no admitidos

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

Por ejemplo, no se admite lo siguiente: all $e.udm.additional.fields["pod_name"] = "kube-scheduler"

Funciones

En esta sección, se describen las funciones de YARA-L 2.0 que admite Chronicle en el motor de detección.

Estas funciones se pueden usar en las siguientes áreas de una regla:

Funciones de string

Chronicle admite las siguientes funciones de manipulación de strings:

  • strings.concat(a; b)
  • strings.coalesce(a; b)
  • strings.to_lower(stringText)
  • strings.to_upper(stringText)
  • strings.base64_decode(encodedString)

En las siguientes secciones, se describe cómo usar cada una.

Concatena strings o números enteros

Muestra la concatenación de dos strings, dos números enteros o una combinación de los dos.

strings.concat(a, b)

Esta función toma dos argumentos, que pueden ser strings o números enteros, y muestra los dos valores concatenados como una string. Los números enteros se convierten en una string antes de la concatenación. Los argumentos pueden ser literales o campos de eventos. Si ambos argumentos son campos, los dos atributos deben ser del mismo evento.

En el siguiente ejemplo, se incluye una variable de string y un literal de string como argumentos.

"google-test" = strings.concat($e.principal.hostname, "-test")

En el siguiente ejemplo, se incluye una variable de string y una variable de número entero como argumentos. Tanto principal.hostname como principal.port provienen del mismo evento, $e, y se concatenan para mostrar una string.

"google80" = strings.concat($e.principal.hostname, $e.principal.port)

En el siguiente ejemplo, se intenta concatenar principal.port del evento $e1, con principal.hostname del evento $e2. Se mostrará un error de compilador porque los argumentos son variables de evento diferentes.

// returns a compiler error
"test" = strings.concat($e1.principal.port, $e2.principal.hostname)

Combina valores de string

Muestra el valor de la primera expresión que no se evalúa como una string vacía (por ejemplo, "non-zero value"). Si ambos argumentos se evalúan como una string vacía, la llamada a función muestra una string vacía.

strings.coalesce(a, b)

Los argumentos pueden ser literales, campos de eventos o llamadas a funciones. Ambos argumentos deben ser del tipo STRING. Si ambos argumentos son campos, los dos atributos deben ser del mismo evento.

En el siguiente ejemplo, se incluye una variable de string y un literal de string como argumentos. La condición se evalúa como verdadera cuando (1) $e.network.email.from es suspicious@gmail.com o (2) $e.network.email.from está vacío y $e.network.email.to es suspicious@gmail.com.

"suspicious@gmail.com" = strings.coalesce($e.network.email.from, $e.network.email.to)

En el siguiente ejemplo, se incluyen las llamadas de combinación anidadas. Esta condición compara la primera dirección IP no nula del evento $e con los valores de la lista de referencia ip_watchlist. El orden en que se combinan los argumentos de esta llamada es el mismo que se enumeran en la condición de la regla:

  1. Primero, se evalúa $e.principal.ip.
  2. A continuación, se evalúa $e.src.ip.
  3. A continuación, se evalúa $e.target.ip.
  4. Finalmente, la string "Sin IP" se muestra como un valor predeterminado si los campos de IP anteriores no están establecidos.
strings.coalesce(
  strings.coalesce($e.principal.ip, $e.src.ip),
  strings.coalesce($e.target.ip, "No IP")
) in %ip_watchlist

En el siguiente ejemplo, se intenta reunir a principal.hostname del evento $e1 y el evento $e2. Se mostrará un error de compilador porque los argumentos son variables de evento diferentes.

// returns a compiler error
"test" = strings.coalesce($e1.principal.hostname, $e2.principal.hostname)

Convierte la string en mayúsculas o minúsculas

Estas funciones muestran texto de string después de cambiar todos los caracteres a mayúscula o minúscula.

  • strings.to_lower(stringText)
  • strings.to_upper(stringText)
"test@google.com" = strings.to_lower($e.network.email.from)
"TEST@GOOGLE.COM" = strings.to_upper($e.network.email.to)

Base64 decodifica una string

Muestra una string que contiene la versión decodificada en Base64 de la string codificada.

strings.base64_decode(encodedString)

Esta función toma una string codificada en base64 como argumento. Si encodedString no es una string codificada en Base64 válida, la función muestra encodedString tal como está.

En este ejemplo, se muestra el valor Verdadero si principal.domain.name es “dGVzdA==", que es la codificación base64 para la string “test”.

"test" = strings.base64_decode($e.principal.domain.name)

Funciones de expresión regular

Chronicle admite las siguientes funciones de expresión regular:

  • re.regex(stringText, regex)
  • re.capture(stringText, regex)
  • re.replace(stringText, replaceRegex, replaceText)

Coincidencia de la expresión regular

Puedes definir la coincidencia de expresiones regulares en YARA-L 2.0 mediante cualquiera de las siguientes sintaxis:

  • Usar la sintaxis de YARA: relacionada con eventos La siguiente es una representación genérica de esta sintaxis: $e.field = /regex/
  • Usar la sintaxis de YARA-L como una función que toma los siguientes parámetros:
    • Campo en el que se aplica la expresión regular.
    • Expresión regular especificada como una string. Puedes usar el modificador nocase después de las strings para indicar que la búsqueda debe ignorar las mayúsculas. La siguiente es una representación genérica de esta sintaxis: re.regex($e.field, `regex`)

Ten en cuenta lo siguiente cuando definas expresiones regulares en YARA-L 2.0:

  • En cualquier caso, el predicado es verdadero si la string contiene una substring que coincide con la expresión regular proporcionada. No es necesario agregar .* al principio ni al final de la expresión regular.
  • Para hacer coincidir la string exacta o solo un prefijo o sufijo, incluye los caracteres de anclaje ^ (comienzo) y $ (final) en la expresión regular. Por ejemplo, /^full$/ coincide exactamente con "full", mientras que /full/ podría coincidir con "fullest", "lawfull" y "joyfully".
  • Si el campo de UDM incluye caracteres de salto de línea, regexp solo coincide con la primera línea del campo del UDM. Para aplicar la coincidencia completa del campo de UDM, agrega un (?s) a la expresión regular. Por ejemplo, reemplaza /.*allUDM.*/ por /(?s).*allUDM.*/.

Captura de la expresión regular

Captura (extrae) los datos de una string con el patrón de expresión regular proporcionado en el argumento.

re.capture(stringText, regex)

Esta función toma dos argumentos:

  • stringText: Es la string original que se va a buscar.
  • regex: La expresión regular que indica el patrón que se debe buscar.

La expresión regular puede contener 0 o 1 grupo de captura entre paréntesis. Si la expresión regular contiene 0 grupos de captura, la función muestra la primera substring completa que coincide. Si la expresión regular contiene 1 grupo de captura, muestra la primera substring que coincide para el grupo de captura. Si se definen dos o más grupos de captura, se muestra un error de compilador.

En este ejemplo, si $e.principal.hostname contiene "aaa1bbaa2", la siguiente sería "True", porque la función muestra la primera instancia. Este ejemplo no tiene grupos de captura.

"aaa1" = re.capture($e.principal.hostname, "a+[1-9]")

En este ejemplo, se captura todo después del símbolo @ de un correo electrónico. Si el campo $e.network.email.from es test@google.com, el ejemplo muestra google.com. Este ejemplo contiene un grupo de captura.

"google.com" = re.capture($e.network.email.from , "@(.*)")

Si la expresión regular no coincide con ninguna substring en el texto, la función muestra una string vacía. Puedes omitir eventos en los que no se produce una coincidencia. Para ello, excluye la string vacía, lo que es especialmente importante cuando usas re.capture() con una desigualdad:

// Exclude the empty string to omit events where no match occurs.
"" != re.capture($e.network.email.from , "@(.*)")

// Exclude a specific string with an inequality.
"google.com" != re.capture($e.network.email.from , "@(.*)")

Reemplazo de expresión regular

Realiza un reemplazo de expresión regular.

re.replace(stringText, replaceRegex, replacementText)

Esta función toma tres argumentos:

  • stringText: es la string original.
  • replaceRegex: la expresión regular que indica el patrón a buscar.
  • reemplazoTexto: El texto que se insertará en cada coincidencia.

Muestra una string nueva derivada de la stringText original, en la que todas las substrings que coinciden con el patrón en replaceRegex se reemplazan por el valor en replacementText. Puedes usar dígitos con escape de barras invertidas (de \1 a \9) dentro de replacementText para insertar texto que coincida con el grupo entre paréntesis correspondiente en el patrón replaceRegex. Usa \0 para hacer referencia a todo el texto coincidente.

La función reemplaza las coincidencias que no se superponen y priorizará el reemplazo del primer caso encontrado. Por ejemplo, re.replace("banana", "ana", "111") muestra la string "b111na".

En este ejemplo, se captura todo después del símbolo @ en un correo electrónico, se reemplaza com por org y, luego, se muestra el resultado. Observa el uso de las funciones anidadas.

"email@google.org" = re.replace($e.network.email.from, "com", "org")

En este ejemplo, se usan dígitos con escape de barra invertida en el argumento replaceText para hacer referencia a las coincidencias con el patrón replaceRegex.

"test1.com.google" = re.replace(
                       $e.principal.hostname, // holds "test1.test2.google.com"
                       "test2\.([a-z]*)\.([a-z]*)",
                       "\\2.\\1"  // \\1 holds "google", \\2 holds "com"
                     )

Ten en cuenta los siguientes casos cuando abordes strings vacías y re.replace():

Usa una string vacía como replaceRegex:

// In the function call below, if $e.principal.hostname contains "name",
// the result is: 1n1a1m1e1, because an empty string is found next to
// every character in `stringText`.
re.replace($e.principal.hostname, "", "1")

Para reemplazar una string vacía, puedes usar "^$" como replaceRegex:

// In the function call below, if $e.principal.hostname contains the empty
// string, "", the result is: "none".
re.replace($e.principal.hostname, "^$", "none")

Funciones de fecha

Chronicle admite las siguientes funciones relacionadas con las fechas:

  • timestamp.get_minute(unix_seconds [, time_zone])
  • timestamp.get_hour(unix_seconds [, time_zone])
  • timestamp.get_day_of_week(unix_seconds [, time_zone])
  • timestamp.get_week(unix_seconds [, time_zone])
  • timestamp.current_seconds()

Chronicle admite números enteros negativos como argumento de unix_seconds. Los números enteros negativos representan los tiempos anteriores a la época Unix. Si proporcionas un número entero no válido (por ejemplo, un valor que da como resultado un desbordamiento), la función mostrará -1. Esta es una situación poco común.

Debido a que YARA-L 2 no admite literales de números enteros negativos, asegúrate de verificar esta condición con el operador menor o mayor que. Por ejemplo:

0 > timestamp.get_hour(123)

Extracción de tiempo

Muestra un número entero en el rango [0, 59].

timestamp.get_minute(unix_seconds [, time_zone])

La siguiente función muestra un número entero en el rango [0, 23], que representa la hora del día.

timestamp.get_hour(unix_seconds [, time_zone])

La siguiente función muestra un número entero en el rango [1, 7] que representa el día de la semana a partir del domingo. Por ejemplo, 1 = domingo; 2 = lunes, etc.

timestamp.get_day_of_week(unix_seconds [, time_zone])

La siguiente función muestra un número entero en el rango [0, 53] que representa la semana del año. Las semanas comienzan con el domingo. Las fechas anteriores al primer domingo del año se encuentran en la semana 0.

timestamp.get_week(unix_seconds [, time_zone])

Estas funciones de extracción de tiempo tienen los mismos argumentos.

  • unix_seconds es un número entero que representa la cantidad de segundos transcurridos en la época de Unix, como $e.metadata.event_timestamp.seconds, o un marcador de posición que contiene ese valor.
  • time_zone es opcional y es una string que representa una time_zone. Si se omite, el valor predeterminado es "GMT". Puedes especificar zonas horarias mediante literales de string. Las opciones son las siguientes:
    • El nombre de la base de datos TZ, por ejemplo "America/Los_Angeles". Para obtener más información, consulta la columna “Nombre de la base de datos TZ” de esta página
    • El desplazamiento de zona horaria desde UTC, en el formato (+|-)H[H][:M[M]], por ejemplo: “-08:00”.

En este ejemplo, se omite el argumento time_zone, por lo que el valor predeterminado es “GMT”.

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_hour($ts) = 15

En este ejemplo, se usa un literal de string para definir la zona horaria.

$ts = $e.metadata.collected_timestamp.seconds

2 = timestamp.get_day_of_week($ts, "America/Los_Angeles")

Estos son algunos ejemplos de otros especificadores de zona horaria válidos, que puedes pasar como el segundo argumento a las funciones de extracción de tiempo:

  • "America/Los_Angeles" o "-08:00". ("PST" no es compatible)
  • "America/New_York" o "-05:00". ("EST" no es compatible)
  • "Europe/London"
  • "UTC"
  • "GMT"

Marca de tiempo actual

Muestra un número entero que representa la hora actual en segundos Unix. Este valor es igual a la marca de tiempo de detección y se basa en cuándo se ejecuta la regla.

timestamp.current_seconds()

En el siguiente ejemplo, se muestra el valor Verdadero si el certificado venció hace más de 24 horas. Calcula la diferencia temporal con la resta de los segundos Unix actuales y, luego, la comparación con un operador mayor que.

86400 < timestamp.current_seconds() - $e.network.tls.certificate.not_after

Funciones matemáticas

Valor absoluto

Muestra el valor absoluto de una expresión de número entero.

math.abs(intExpression)

Este ejemplo muestra el valor Verdadero si el evento estuvo a más de 5 minutos de la hora especificada (en segundos a partir del epoch Unix), sin importar si el evento ocurrió antes o después de la hora especificada. Una llamada a math.abs no puede depender de varias variables ni de marcadores de posición. Por ejemplo, no puedes reemplazar el valor de tiempo codificado de 1643687343 en el siguiente ejemplo por $e2.metadata.event_timestamp.seconds.

300 < math.abs($e1.metadata.event_timestamp.seconds - 1643687343)

Funciones de red

Muestra true cuando la dirección IP dada está dentro de la subred especificada.

net.ip_in_range_cidr(ipAddress, subnetworkRange)

Puedes usar YARA-L para buscar eventos de UDM en todas las direcciones IP de una subred mediante la declaración net.ip_in_range_cidr(). Se admiten IPv4 e IPv6.

Para buscar en un rango de direcciones IP, especifica un campo UDM de IP y un rango de enrutamiento entre dominios sin clases (CIDR). YARA-L puede manejar campos de direcciones IP tanto singulares como recurrentes.

Ejemplo de IPv4:

net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")

Ejemplo de IPv6:

net.ip_in_range_cidr($e.network.dhcp.yiaddr, "2001:db8::/32")

Para ver una regla de ejemplo que usa la declaración net.ip_in_range_cidr(), consulta la regla de ejemplo. Un solo evento en el rango de direcciones IP

Asignación de función a marcador de posición

Puedes asignar el resultado de una llamada a una función a un marcador de posición en la sección events. Por ejemplo:

$placeholder = strings.concat($e.principal.hostname, "my-string").

Luego, puedes usar las variables de marcador de posición en las secciones match, condition y outcome. Sin embargo, existen dos limitaciones con la asignación de la función para el marcador de posición:

  1. Cada marcador de posición en función de la asignación del marcador de posición debe asignarse a una expresión que contenga un campo de evento. Por ejemplo, los siguientes ejemplos son válidos:

    $ph1 = $e.principal.hostname
    $ph2 = $e.src.hostname
    
    // Both $ph1 and $ph2 have been assigned to an expression containing an event field.
    $ph1 = strings.concat($ph2, ".com")
    
    $ph1 = $e.network.email.from
    $ph2 = strings.concat($e.principal.hostname, "@gmail.com")
    
    // Both $ph1 and $ph2 have been assigned to an expression containing an event field.
    $ph1 = strings.to_lower($ph2)
    

    Sin embargo, el siguiente ejemplo no es válido:

    $ph1 = strings.concat($e.principal.hostname, "foo")
    $ph2 = strings.concat($ph1, "bar") // $ph2 has NOT been assigned to an expression containing an event field.
    
  2. La llamada a función debe depender de un solo evento. Sin embargo, se puede usar más de un campo del mismo evento en los argumentos de la llamada de función. Por ejemplo:

    $ph = strings.concat($event.principal.hostname, "string2")

    $ph = strings.concat($event.principal.hostname, $event.src.hostname)

    Sin embargo, lo siguiente no es válido:

    $ph = strings.concat("string1", "string2")

    $ph = strings.concat($event.principal.hostname, $anotherEvent.src.hostname)

Sintaxis de las listas de referencia

Consulta nuestra página sobre listas de referencia para obtener más información sobre su comportamiento y su sintaxis.

Puedes usar listas de referencia en las secciones events o outcome. Esta es la sintaxis para usar varios tipos de listas de referencia en una regla:

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

También puedes usar el operador not con listas de referencia como se muestra aquí: not $e.principal.hostname in regex %my_regex_list.

Por motivos de rendimiento, el motor de detección restringe el uso de las listas de referencia. Puedes usar hasta 7 declaraciones in en una regla y puedes usar varios tipos de declaraciones in en la misma regla. Como máximo, 2 de las 7 declaraciones in pueden usar los operadores especiales regex o cidr.

El operador nocase no funciona con las listas de referencia. No es recomendable colocar nocase después de una llamada a una lista de referencia, por lo que no se recomienda.

Sintaxis de la sección meta

La metasección está compuesta por varias líneas, en las que cada línea define un par clave-valor. Una parte de la clave debe ser una string sin comillas, y una parte del valor debe ser una string entre comillas:

<key> = "<value>"

A continuación, se muestra un ejemplo de una línea de sección válida de meta: meta: author = "Chronicle" severity = "HIGH"

Sintaxis de la sección Eventos

En la sección events, enumera los predicados para especificar lo siguiente:

  • Qué representa cada variable de coincidencia o marcador de posición
  • Expresiones binarias simples como condiciones
  • Expresiones de funciones como condiciones
  • Expresiones de lista de referencia como condiciones
  • Operadores lógicos

Declaraciones de variables

Para las declaraciones de variables, usa la siguiente sintaxis:

  • <EVENT_FIELD> = <VAR>
  • <VAR> = <EVENT_FIELD>

Ambos son equivalentes, como se muestra en los siguientes ejemplos:

  • $e.source.hostname = $hostname
  • $userid = $e.principal.user.userid

Esta declaración indica que esta variable representa el campo especificado para la variable del evento. Cuando el campo de evento es un campo repetido, la variable de coincidencia puede representar cualquier valor en el arreglo. También es posible asignar varios campos de evento a una sola coincidencia o variable de marcador de posición. Esta es una condición de unión transitiva.

Por ejemplo:

  • $e1.source.ip = $ip
  • $e2.target.ip = $ip

Son equivalentes a los siguientes:

  • $e1.source.ip = $ip
  • $e1.source.ip = $e2.target.ip

Cuando se usa una variable, esta debe declararse mediante una declaración de variable. Si se usa una variable sin ninguna declaración, se considera un error de compilación.

Expresiones binarias simples como condiciones

Para que una expresión binaria simple se use como condición, usa la siguiente sintaxis:

  • <EXPR> <OP> <EXPR>

La expresión puede ser un campo de evento, una variable, un literal o una expresión de función.

Por ejemplo:

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

Si ambos lados son literales, se considera un error de compilación.

Expresiones de funciones como condiciones

Algunas expresiones de función muestran un valor booleano, que se puede usar como predicado individual en la sección events. Estas funciones son:

  • re.regex()
  • net.ip_in_range_cidr()

Por ejemplo:

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

Expresiones de lista de referencia como condiciones

Puedes usar listas de referencia en la sección de eventos. Consulta la sección sobre listas de referencia para obtener más información.

Operadores lógicos

Puedes usar los operadores lógicos and y or lógicos en la sección events, como se muestra en los siguientes ejemplos:

  • $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, or.

Por ejemplo, "a or b and c" se evalúa como "a or (b and c)". Puedes usar paréntesis para modificar la prioridad si es necesario.

En la sección events, todos los predicados se consideran and de forma predeterminada.

Operadores en eventos

Puedes usar los operadores con tipos enumerados. Puede aplicarse a reglas para simplificar y optimizar el rendimiento (usar un operador 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"

Lista de eventos:

  • USER_RESOURCE_DELETION
  • USER_RESOURCE_UPDATE_CONTENT
  • USER_RESOURCE_UPDATE_PERMISSIONS
  • ESTADÍSTICAS DE USUARIO
  • USER_UNCATEGORIZED

Teclas modificadoras

sin caso

Cuando tienes una expresión de comparación entre valores de string o una expresión regex, puedes agregar mayúscula al final de la expresión para ignorar el uso de mayúsculas.

  • $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

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

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

Campos repetidos

cualquiera, todo

En UDM y entidades, algunos campos se etiquetan como repetidos, lo que indica que son listas de valores o de otros tipos de mensajes. En YARA-L, cada elemento del campo repetido se trata de forma individual. Esto significa que, si se usa el campo repetido en la regla, se evalúa la regla para cada elemento del campo. Esto puede generar un comportamiento inesperado. Por ejemplo, si una regla tiene $e.principal.ip = "1.2.3.4" y $e.principal.ip = "5.6.7.8" en la sección events, la regla nunca genera coincidencias, incluso si tanto "1.2.3.4" como "5.6.7.8" están en principal.ip.

Para evaluar todo el campo repetido, puedes usar los operadores any y all. Cuando se usa any, el predicado se evalúa como verdadero si algún valor en el campo repetido cumple la condición. Cuando se usa all, el predicado se evalúa como verdadero si todos los valores en el campo repetido cumplen la condición.

  • any $e.target.ip = "127.0.0.1"
  • all $e.target.ip != "127.0.0.1"
  • re.regex(any $e.about.hostname, `server-[0-9]+`)
  • net.ip_in_range_cidr(all $e.principal.ip, "10.0.0.0/8")

Los operadores any y all solo se pueden usar con campos repetidos. Además, no se pueden utilizar cuando se asigna un campo repetido a una variable de marcador de posición o cuando se unen con un campo de otro evento.

Por ejemplo, any $e.principal.ip = $ip y any $e1.principal.ip = $e2.principal.ip no son sintaxis válidas. Para hacer coincidir un campo repetido o unirse a él, usa $e.principal.ip = $ip. Habrá una unión o valor de variable coincidente para cada elemento del campo repetido.

Cuando escribas una condición con any o all, ten en cuenta que la negación de la condición con not podría no tener el mismo significado que el uso del operador denegado.

Por ejemplo:

  • not all $e.principal.ip = "192.168.12.16" verifica si no todas las direcciones IP coinciden con "192.168.12.16", lo que significa que la regla verifica si alguna dirección IP no coincide con "192.168.12.16".
  • all $e.principal.ip != "192.168.12.16" verifica si todas las direcciones IP no coinciden con "192.168.12.16", lo que significa que la regla verifica que ninguna dirección IP coincida con "192.168.12.16".

Requisitos para unirse a la variable de evento

Todas las variables de eventos que se usan en la regla deben combinarse con todas las demás variables de evento de las siguientes maneras:

  • directamente a través de una comparación de igualdad entre los campos de evento de las dos variables de evento unidas, por ejemplo: $e1.field = $e2.field. La expresión no debe incluir llamadas aritméticas o de funciones.

  • de manera indirecta a través de una unión transitiva que involucra solo un campo de evento (consulte la declaración de variable para ver una definición de "unión transitiva"). La expresión no debe incluir llamadas aritméticas o de funciones.

Por ejemplo, si se usan $e1, $e2 y $e3 en la regla, las siguientes secciones events son válidas.

events:
  $e1.principal.hostname = $e2.src.hostname // $e1 joins with $e2
  $e2.principal.ip = $e3.src.ip // $e2 joins with $e3
events:
  // all of $e1, $e2 and $e3 are transitively joined via the placeholder variable $ip
  $e1.src.ip = $ip
  $e2.target.ip = $ip
  $e3.about.ip = $ip
events:
  $e1.principal.hostname = $e2.src.hostname // $e1 joins with $e2

  // Function to event comparison is not a valid join condition for $e1 and $e2,
  // but the whole events section is valid because we have a valid join condition in the first line.
  re.capture($e1.src.hostname, ".*") = $e2.target.hostname

Sin embargo, aquí tienes ejemplos de secciones events no válidas.

events:
  // Event to function comparison is an invalid join condition for $e1 and $e2.
  $e1.principal.hostname = re.capture($e2.principal.application, ".*")
events:
  // Event to arithmetic comparison is an invalid join condition for $e1 and $e2.
  $e1.principal.port = $e2.src.port + 1
events:
  $e1.src.ip = $ip
  $e2.target.ip = $ip
  $e3.about.ip = "192.1.2.0" //$e3 is not joined with $e1 or $e2.
events:
  $e1.src.ip = $ip

  // Function to placeholder comparison is an invalid transitive join condition.
  re.capture($e2.target.ip, ".*") = $ip
events:
  $e1.src.port = $port

  // Arithmetic to placeholder comparison is an invalid transitive join condition.
  $e2.principal.port + 800 = $port

Coincidir con la sintaxis de la sección

En la sección match, enumera las variables de coincidencia de los eventos de grupo antes de verificar las condiciones de coincidencia. Esos campos se muestran con cada coincidencia.

  • Especifica qué representa cada variable de coincidencia en la sección events.
  • Especifica el intervalo de tiempo que se usará para correlacionar eventos después de la palabra clave over. Se ignoran los eventos que se encuentran fuera del intervalo de tiempo.
  • Usa la siguiente sintaxis para especificar el intervalo de tiempo: <number><s/m/h/d>. En el ejemplo anterior, s/m/h/d significa segundos, minutos, horas y días, respectivamente.
  • El tiempo mínimo que puedes especificar es 1 minuto.
  • El tiempo máximo que puedes especificar es de 48 horas.

El siguiente es un ejemplo de un match válido:

$var1, $var2 over 5m

Esta sentencia muestra $var1 y $var2 (definidos en la sección events) cuando la regla encuentra una coincidencia. El tiempo especificado es de 5 minutos. Los eventos que se encuentren a más de 5 minutos de diferencia no se correlacionan, por lo que la regla los ignora.

Este es otro ejemplo de un match válido:

$user over 1h

Esta declaración muestra $user cuando la regla encuentra una coincidencia. El período especificado es de 1 hora. Los eventos que tienen una diferencia de más de una hora no se correlacionan. La regla no los considera de detección.

Este es otro ejemplo de un match válido:

$source_ip, $target_ip, $hostname over 2m

Esta sentencia muestra $source_ip, $target_ip y $hostname cuando la regla encuentra una coincidencia. El período especificado es de 2 minutos. Los eventos que están a más de 2 minutos de diferencia no se correlacionan. La regla no los considera de detección.

En los siguientes ejemplos, se ilustran las secciones no válidas match:

  • var1, var2 over 5m // invalid variable name
  • $user 1h // missing keyword

Ventana deslizante

De forma predeterminada, las reglas YARA-L 2.0 se evalúan mediante ventanas de salto. Un intervalo de tiempo de los datos de eventos empresariales se divide en un conjunto de ventanas de salto superpuestas, cada una con la duración especificada en la sección match. Luego, los eventos se correlacionan dentro de cada ventana de salto. Con las ventanas de salto, es imposible buscar eventos que ocurran en un orden específico (por ejemplo, e1 ocurre hasta 2 minutos después de e2). Un caso del evento e1 y uno del evento e2 se correlacionan siempre que estén dentro de la duración del período de salto de cada uno.

Las reglas también se pueden evaluar con ventanas variables. Con las ventanas deslizantes, las ventanas deslizantes con la duración especificada en la sección match se generan cuando comienza o finaliza con una variable de evento dinámica especificada. Luego, los eventos se correlacionan dentro de cada ventana deslizante. Esto permite buscar eventos que ocurran en un orden específico (por ejemplo, e1 ocurre dentro de los 2 minutos de e2). Un caso del evento e1 y uno del evento e2 se correlacionan si el evento e1 ocurre dentro de la duración de la ventana deslizante después del evento e2.

Especifica las ventanas deslizantes en la sección match de una regla de la siguiente manera:

<match-var-1>, <match-var-2>, ... over <duration> before|after <pivot-event-var>

La variable de evento dinámica es la variable de evento en la que se basan las ventanas deslizantes. Si usas la palabra clave before, se generan ventanas variables que terminan con cada caso del evento de tabla dinámica. Si se usa la palabra clave after, las ventanas deslizantes se generan a partir de cada caso del evento de tabla dinámica.

Los siguientes son ejemplos de usos válidos de ventanas deslizantes:

  • $var1, $var2 over 5m after $e1
  • $user over 1h before $e2

Sintaxis de la sección de resultados

En la sección outcome, puedes definir hasta 20 variables de resultado, con nombres arbitrarios. Estos resultados se almacenarán en las detecciones que genera la regla. Cada detección puede tener valores diferentes para los resultados.

El nombre del resultado, $risk_score, es especial. De manera opcional, puedes definir un resultado con este nombre y, si lo haces, debe ser un tipo de número entero. Si se propaga, risk_score se mostrará en la vista Enterprise Insights para las alertas que provienen de detecciones de reglas.

Tipos de datos de las variables de resultados

Cada variable de resultado puede tener un tipo de datos diferente, que lo determina la expresión que se usa para procesarla. Se admiten los siguientes tipos de datos de resultados:

  • integer
  • string
  • listas de números enteros
  • listas de strings

Lógica condicional

Puedes usar la lógica condicional para calcular el valor de un resultado. Los condicionales se especifican con el siguiente patrón de sintaxis:

if(BOOL_CLAUSE, THEN_CLAUSE)
if(BOOL_CLAUSE, THEN_CLAUSE, ELSE_CLAUSE)

Puedes leer una expresión condicional como “si BOOL_CLAUSE es verdadero, luego mostrar THEN_CLAUSE; de lo contrario, mostrar ELSE_CLAUSE”.

BOOL_CLAUSE debe evaluarse como un valor booleano. Una expresión BOOL_CLAUSE toma una forma similar a las expresiones en la sección events. Por ejemplo, puede incluir lo siguiente:

  • Nombres de campos de UDM con operador de comparación, por ejemplo:

    if($context.graph.entity.user.title = "Vendor", 100, 0)

  • variable del marcador de posición que se definió en la sección events. Por ejemplo:

    if($severity = "HIGH", 100, 0)

  • funciones que muestran un valor booleano, por ejemplo:

    if(re.regex($e.network.email.from, .*altostrat\.com), 100, 0)

  • buscar en una lista de referencia, por ejemplo:

    if($u.principal.hostname in %my_reference_list_name, 100, 0)

THEN_CLAUSE y ELSE_CLAUSE deben ser del mismo tipo de datos. Se admiten números enteros y strings.

Puedes omitir ELSE_CLAUSE si el tipo de datos es un número entero. Si se omite, ELEL_CLAUSE se evalúa como 0. Por ejemplo:

`if($e.field = "a", 5)` is equivalent to `if($e.field = "a", 5, 0)`

Debes proporcionar ELSE_CLAUSE si el tipo de datos es una string.

Operaciones matemáticas

Puedes usar operaciones matemáticas para calcular los resultados de tipos de datos de números enteros. Admitimos la suma y resta (pero no la multiplicación, la división o el módulo) como los operadores de nivel superior en un cálculo de resultado. Por ejemplo:

outcome:
  $risk_score = max(100 + if($severity = "HIGH", 10, 5) - if($severity = "LOW", 20, 0))

Variables del marcador de posición en los resultados

Cuando procesas variables de resultados, puedes usar variables de marcador de posición que se definieron en la sección de eventos de tu regla. En este ejemplo, supongamos que $email_sent_bytes se definió en la sección de eventos de la regla:

Ejemplo de un solo evento:

// No match section, so this is a single-event rule.

outcome:
  // Use placeholder directly as an outcome value.
  $my_outcome = $email_sent_bytes

  // Use placeholder in a conditional.
  $other_outcome = if($file_size > 1024, "SEVERE", "MODERATE")

condition:
  $e

Ejemplo de varios eventos:

match:
  // This is a multi event rule with a match section.
  $hostname over 5m

outcome:
  // Use placeholder directly in an aggregation function.
  $max_email_size = max($email_sent_bytes)

  // Use placeholder in a mathematical computation.
  $total_bytes_exfiltrated = sum(
    1024
    + $email_sent_bytes
    + $file_event.principal.file.size
  )

condition:
  $email_event and $file_event

Datos recopilados

La sección de resultados se puede usar en reglas de varios eventos (reglas que contienen una sección de coincidencia) y en reglas de un solo evento (reglas que no contienen una sección de coincidencia). Los requisitos para las agregaciones son los siguientes:

  • Reglas de varios eventos (con sección de coincidencia)

    • La expresión a los resultados de procesamiento se evalúa en todos los eventos que generaron una detección en particular.
    • La expresión debe estar integrada en una función agregada.
      • Ejemplo: $max_email_size = max($e.network.sent_bytes)
      • Si la expresión contiene un campo repetido, el agregado opera sobre todos los elementos del campo repetido y sobre todos los eventos que generaron la detección.
  • Reglas de evento único (sin sección de coincidencia)

    • La expresión a los resultados de procesamiento se evalúa en el único evento que generó una detección en particular.
    • Se debe usar la función de agregación para expresiones que impliquen al menos un campo repetido
      • Ejemplo: $suspicious_ips = array($e.principal.ip)
      • El agregado opera sobre todos los elementos del campo repetido
    • No se puede usar la función agregada para expresiones que no involucran un campo repetido.
      • Ejemplo: $threat_status = if($e.principal.file.size > 1024, "SEVERE", "MODERATE")

Puedes usar las siguientes funciones de agregación:

  • max(): Muestra el máximo en todos los valores posibles. Solo funciona con números enteros.
  • min(): Muestra el mínimo en todos los valores posibles. Solo funciona con números enteros.
  • sum(): Muestra la suma en todos los valores posibles. Solo funciona con números enteros.
  • count_distinct(): Recopila todos los valores posibles y, luego, da como resultado un recuento distinto de los valores posibles.
  • count(): Se comporta como count_distinct(), pero muestra un recuento no distinto de valores posibles.
  • array_distinct(): Recopila todos los valores posibles y, luego, genera una lista de estos valores. Se truncará la lista de valores en 25 elementos aleatorios.
  • array(): Se comporta como array_distinct(), pero muestra una lista de valores no distintos. También trunca la lista de valores a 25 elementos aleatorios.

La función agregada es importante cuando una regla incluye una sección condition que especifica que deben existir varios eventos, ya que la función agregada operará en todos los eventos que generaron la detección.

Por ejemplo, si las secciones outcome y condition contienen lo siguiente:

outcome:
  $asset_id_count = count($event.principal.asset_id)
  $asset_id_distinct_count = count_distinct($event.principal.asset_id)

  $asset_id_list = array($event.principal.asset_id)
  $asset_id_distinct_list = array_distinct($event.principal.asset_id)

condition:
  #event > 1

Como la sección de condición requiere que haya más de un event para cada detección, las funciones de agregación operarán en varios eventos. Supongamos que los siguientes eventos generaron una detección:

event:
  // UDM event 1
  asset_id="asset-a"

event:
  // UDM event 2
  asset_id="asset-b"

event:
  // UDM event 3
  asset_id="asset-b"

Entonces, los valores de sus resultados serán los siguientes:

  • Recuento de ID de recursos ($asset_id_count) = 3
  • $asset_id_distinct_count = 2
  • $asset_id_list = ["asset-a", "asset-b", "asset-b"]`
  • $asset_id_distinct_list = ["asset-a", "asset-b"]

Debes saber lo siguiente cuando uses la sección de resultados:

Otras notas y restricciones:

  • La sección outcome no puede hacer referencia a una nueva variable de marcador de posición que no estaba definida en la sección events.
  • La sección outcome no puede usar variables de eventos que no se definieron en la sección events.
  • La sección outcome puede usar un campo de evento que no se usó en la sección events, ya que la variable de evento a la que pertenece el campo de evento ya estaba definida en la sección events.
  • La sección outcome solo puede correlacionar variables de eventos que ya se correlacionaron en la sección events. Las correlaciones ocurren cuando se equiparan dos campos de eventos de diferentes variables de eventos.

Puedes encontrar un ejemplo en la sección de resultados de Descripción general de YARA-L 2.0. Consulta Crea estadísticas contextuales para obtener detalles sobre la anulación de duplicación con la sección de resultados.

Sintaxis de la sección de condiciones

En la sección condition, puedes hacer lo siguiente:

  • especificar una condición de coincidencia sobre eventos y marcadores de posición definidos en la sección events. Para obtener más información, consulta la siguiente sección, Condicionales de eventos y marcadores de posición.
  • (opcional) Usa la palabra clave and para especificar una condición de coincidencia mediante las variables de resultado definidas en la sección outcome. Consulta la siguiente sección, Condicionales de resultados para obtener más detalles.

Los siguientes patrones de condición son válidos:

condition:
  <event/placeholder conditionals>
condition:
  <event/placeholder conditionals> and <outcome conditionals>

Condicionales de eventos y marcadores de posición

Aquí se enumeran los predicados de condición para variables de eventos y marcadores de posición, unidos con la palabra clave and o or.

Las siguientes son condiciones de límite. Hacen que la variable de evento asociada exista, lo que significa que al menos una instancia del evento debe aparecer en cualquier detección.

  • $var // equivalent to #var > 0
  • #var > n // where n >= 0
  • #var >= m // where m > 0

Las siguientes condiciones son condiciones no delimitantes. Permiten que la variable de evento asociada no exista, lo que significa que es posible que no aparezca ningún evento en una detección. Esto permite crear reglas que no existen, que buscan la ausencia de una variable en lugar de una presencia de una variable.

  • !$var // equivalent to #var = 0
  • #var >= 0
  • #var < n // where n > 0
  • #var <= m // where m >= 0

En el siguiente ejemplo, el carácter especial # en una variable (la variable del evento o la variable del marcador de posición) representa el recuento de eventos o valores distintos de esa variable.

$e and #port > 50 or #event1 > 2 or #event2 > 1 or #event3 > 0

El siguiente ejemplo de inexistencia también es válido y se evalúa como verdadero si hay más de dos eventos distintos de $event1 y cero eventos distintos de $event2.

#event1 > 2 and !$event2

Los siguientes son ejemplos de predicados no válidos:

  • $e, #port > 50 // incorrect keyword usage
  • $e or #port < 50 // or keyword not supported with non-bounding conditions
  • not $e // not keyword is not allowed for event and placeholder conditions

Condicionales de resultados

Enumere los predicados de las condiciones para las variables de resultado aquí, combinados con la palabra clave and o or, o precedidos por la palabra clave not.

Especifica condicionales de resultado de manera diferente según el tipo de variable de resultado:

  • integer: Compare con un literal de número entero con los operadores =, >, >=, <, <=, !=, por ejemplo:

    $risk_score > 10

  • string: Compara un literal de string con = o !=, por ejemplo:

    $severity = "HIGH"

  • Lista de números enteros o arreglos: especifica la condición con la función arrays.contains, por ejemplo:

    arrays.contains($event_ids, "id_1234")

Clasificación de reglas

Si especifica un resultado condicional en una regla que tiene una sección de coincidencia, la regla se clasificará como una regla de varios eventos para la cuota de reglas. Consulte las reglas de eventos individuales y varias reglas para obtener más información sobre las clasificaciones de los eventos.

Recuento (#) carácter

El carácter # es un carácter especial en la sección condition. Si se usa antes de cualquier nombre de variable de evento o marcador de posición, representa la cantidad de eventos o valores distintos que satisfacen todas las condiciones de la sección events.

Valor ($) carácter

El carácter $ es otro carácter especial en la sección condition. Si se usa antes de cualquier nombre de variable de resultado, representa el valor de ese resultado.

Si se usa antes de cualquier nombre de variable de evento o marcador de posición (por ejemplo, $event), es una forma abreviada de #event > 0.

Sintaxis de la sección de opciones

En la sección options, puedes especificar las opciones de la regla. La sintaxis de la sección options es similar a la de la sección meta. Sin embargo, una clave debe ser uno de los nombres de opciones predefinidos y el valor no se limita al tipo de string.

Actualmente, la única opción disponible es allow_zero_values.

  • allow_zero_value: Si se establece como verdadera, las coincidencias generadas por la regla pueden tener cero valores como valores de variable coincidentes. Los campos de evento no tienen ningún valor cuando no se completan. Esta opción se establece como falsa de forma predeterminada.

A continuación, se encuentra la línea de la sección options válida:

  • allow_zero_values = true

Comprobación de tipos

Chronicle realiza la verificación de tipo con tu sintaxis YARA-L mientras creas reglas dentro de la interfaz. Los errores de comprobación de tipo que se muestran te ayudan a revisar la regla de tal manera que garantice que funcione según lo esperado.

Los siguientes son ejemplos de predicados no válidos:

// $e.target.port is of type integer which cannot be compared to a string.
$e.target.port = "80"

// "LOGIN" is not a valid event_type enum value.
$e.metadata.event_type = "LOGIN"