Expresiones, operadores y otras construcciones
Este documento incluye información que te ayudará a crear reglas y consultas de YARA-L mediante expresiones.
Expresiones booleanas
Las expresiones booleanas son expresiones de tipo booleano, que incluyen expresiones de comparación, expresiones de función y expresiones de lista de referencias o de tabla de datos. Puedes usar expresiones booleanas en la sección 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 evento, variables, literales o expresiones de función.
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 predicado individual en la sección events, como:
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
Puede usar listas de referencia o tablas de datos en las secciones events o outcome. Consulta Listas de referencia y Usar 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 de las listas de referencias
En los siguientes ejemplos se muestra la sintaxis de varios tipos de listas de referencia en una consulta:
// 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 de las 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: usar not y nocase en la sintaxis de las listas de referencias
// 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 referencias y tablas de datos tiene las siguientes limitaciones:
- Número máximo de instrucciones
inen una consulta, con o sin operadores especiales: 7 - Número máximo de instrucciones
incon el operadorregex: 4 - Número máximo de instrucciones
incon el operadorcidr: 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 precedencia 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 explícitamente en la expresión.
En la sección events, los predicados se unen mediante el operador and si no se define explícitamente ningún operador. 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 explícitamente y el operador and se da por 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 explícitamente, los predicados circundantes se agrupan y se evalúan primero. El último predicado, $e2.field = "bar". se une implícitamente mediante and. El resultado es que el orden de evaluación cambia.
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 las mayúsculas y minúsculas en una expresión de comparación entre valores de cadena o una expresión regular, añade 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. Para indicar un comentario, se usa el carácter de barra inclinada:
- Para añadir un comentario de una sola línea, usa dos barras inclinadas (
// comment). - Para añadir un comentario de varias líneas, usa una barra inclinada y un asterisco (
/* comment */).
Literales
YARA-L admite números enteros y flotantes 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 (entre barras diagonales) para la coincidencia de patrones y valores booleanos (true o false) 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 forma diferente en función del tipo de comillas que utilices:
- Comillas dobles ("hola\tmundo"): se usan para cadenas normales. Se deben incluir caracteres de escape, donde \t se interpreta como una tabulación.
- Comillas inversas (`hello\tworld`): se usan cuando todos los caracteres se deben interpretar de forma literal, donde \t no se interpreta como una tabulación.
Literales de expresiones regulares
En el caso de los literales de expresiones regulares, tienes dos opciones:
Si quieres usar expresiones regulares directamente sin la función
re.regex(), usa/regex/para los literales de expresiones regulares.Si quieres usar literales de cadena como literales de expresión regular, usa la función
re.regex(). Ten en cuenta que, en el caso de los literales de cadena entre comillas dobles, debes usar el carácter de barra inversa para escapar el carácter de barra inversa, lo que puede resultar 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 comillas inversas para las cadenas de las expresiones regulares, ya que así se leen mejor.
Operadores
| Operador | Descripción |
| = | igual/declaración |
| != | no es igual a |
| < | 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 evento representan grupos de eventos o eventos de entidad. En la sección events, especifica las condiciones de las variables de evento mediante un nombre, una fuente de evento y campos de evento.
Las fuentes de eventos son
udm(para eventos normalizados) ygraph(para eventos de entidad). Si se omite la fuente, se defineudmcomo fuente predeterminada.Los campos de evento se representan como una cadena de .<nombre del campo> (por ejemplo, $e.field1.field2) y las cadenas de campos siempre empiezan por 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 en función de valores comunes en un periodo específico.
Se convierten en campos de agrupación de la consulta, ya que se devuelve una fila por cada conjunto único de variables de coincidencia (y por cada ventana temporal). Cuando la consulta encuentra una coincidencia, se devuelven los valores de las variables de coincidencia.
En la sección events, especifica qué representa cada variable de coincidencia.
Variables de marcador de posición
Las variables de marcador de posición se usan para registrar y almacenar valores específicos de los campos de eventos de UDM que se pueden consultar y usar en una consulta. Se usan para vincular eventos dispares, especialmente en consultas de varios eventos. Si asigna un valor común (por ejemplo, userid o hostname) a un marcador de posición, puede usarlo en la sección match para agrupar los eventos que compartan ese valor en un periodo concreto.
Para definir variables de marcador de posición en la sección events, asigne el valor de un campo de 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:
conditionpara especificar las condiciones que deben cumplirse.outcomepara hacer cálculos, definir métricas o extraer puntos de datos específicos de los eventos coincidentes.matchpara 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 consulta, realizar operaciones lógicas y matemáticas, y definir condiciones para que coincidan los eventos. Estas palabras clave no se pueden usar como identificadores de 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 incluye las palabras clave principales que se usan en YARA-L 2.0 para crear consultas de detección sólidas.
- Definición de la consulta:
rule: inicia la definición de una nueva consulta de YARA-L.private: designa una consulta como privada, lo que impide que se exponga o se active directamente de forma externa.global: marca una consulta como global, lo que indica que debe aplicarse de forma general.
- Secciones de la consulta:
meta: introduce la sección de metadatos para obtener información descriptiva sobre la consulta.strings: denota la sección en la que se definen los patrones de cadena.condition: especifica la sección que contiene la lógica booleana para activar la consulta.events: define la sección para especificar las variables de evento y sus condiciones.match: introduce la sección para agregar valores en un periodo.outcome: define la sección para añadir contexto y puntuación a las consultas activadas.
- Modificadores de cadena:
ascii: especifica que una cadena debe coincidir con texto ASCII.wide: indica que una cadena debe coincidir con caracteres anchos (UTF-16).nocase: realiza una búsqueda de cadenas sin distinguir 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 buscar coincidencias.
- 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 en 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 empieza o termina con una subcadena.icontains,istartswith,iendswithyiequals: versiones que no distinguen entre mayúsculas y 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: 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 está analizando.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 de 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 de campo de estructura:
$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 e inválido de los mapas.
Uso válido de los mapas
Usar un campo Struct en la sección de eventos:
events: $e.udm.additional.fields["pod_name"] = "kube-scheduler"
Usar un campo de etiqueta en la sección de resultados:
outcome: $value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])
Asignar un valor de mapa a un marcador de posición:
$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]
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
Combinar palabras clave any o all con un mapa
all $e.udm.additional.fields["pod_name"] = "kube-scheduler"
Otros tipos de valores
La sintaxis de los mapas 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 se puede acceder a las claves cuyos valores sean otros tipos primitivos, como los números enteros.
Gestión de valores duplicados en mapas
El acceso al mapa está pensado para recuperar un único valor asociado a una clave específica. Este es el comportamiento estándar y esperado.
Sin embargo, en situaciones poco frecuentes, el contexto de map access puede apuntar inadvertidamente a varios valores. En el caso poco habitual de que el acceso al mapa haga referencia a varios valores, map access devolverá el primer valor de forma determinista. Esto puede ocurrir si una etiqueta tiene una clave duplicada o un campo repetido de ancestro.
La etiqueta tiene una clave duplicada
La estructura de la etiqueta representa un mapa, pero no exige que las claves sean únicas. Por convención, un mapa debe tener claves únicas, por lo que Google SecOps no recomienda rellenar una etiqueta con claves duplicadas.
Ejemplo: etiqueta con clave duplicada
El texto de la consulta $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 antecesor
Un campo repetido puede contener una etiqueta como campo secundario. Dos entradas diferentes del campo repetido de nivel superior pueden contener etiquetas que tengan la misma clave.
Ejemplo: etiqueta con campo repetido de ancestro
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"
}
}
}
Acceder a las variables de resultados en los mapas
En esta sección se explica cómo acceder a las variables de resultado de los mapas con sus tipos de datos originales (por ejemplo, números enteros, booleanos o listas de estos tipos) en lugar de solo cadenas. Puedes usar esta función para que la lógica de tus consultas sea más flexible y precisa.
Los datos de resultados están disponibles en los siguientes campos:
- Los valores de los resultados conservan sus tipos originales en el campo
variables. - El campo
outcomesalmacena versiones destringpara la retrocompatibilidad.
Puedes acceder a estos valores de resultado mediante el mapa variables
para obtener el tipo específico o acceder a los elementos de una secuencia mediante 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 individualmente.
Sintaxis:
$d.detection.detection.variables[OUTCOME_NAME].TYPE_SUFFIX
Sintaxis de las secuencias:
$d.detection.detection.variables[OUTCOME_NAME].SEQUENCE_TYPE_SUFFIX.TYPE_VALS_SUFFIX
Ejemplos: acceder a variables de resultados en mapas
Acceder al resultado de una cadena:
$my_string_outcome = $d.detection.detection.variables["outcome_ip"].string_val
En este ejemplo, se obtiene el valor de cadena directamente (por ejemplo, "1.1.1.1" si outcome_ip era una sola cadena).
Acceder a un resultado entero
$my_int_outcome = $d.detection.detection.variables["outcome_port"].int64_value
En este ejemplo, se recupera el valor entero (por ejemplo, 30).
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 obtiene la lista completa de números enteros y se desanidan como
campos repetidos (por ejemplo, [2, 3, 4]).
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 obtiene el primer número entero de la lista (por ejemplo, 2).
Acceder a una lista de cadenas (StringSequence)
$my_string_list = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals
En este ejemplo se obtiene la lista completa de cadenas y se desanidan como
campos repetidos (por ejemplo, ["1.1.1.1", "2.2.2.2"]).
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 obtiene la primera dirección IP de la lista (por ejemplo, "1.1.1.1").
Sufijos de tipo disponibles para variables
Para ver una lista completa de los sufijos admitidos, consulta FindingVariable.
¿Necesitas más ayuda? Recibe respuestas de los miembros de la comunidad y de los profesionales de Google SecOps.