Sintassi del linguaggio YARA-L 2.0

Questa sezione descrive i principali elementi della sintassi YARA-L. Vedi anche Panoramica della lingua YARA-L 2.0.

Struttura della regola

Per YARA-L 2.0, devi specificare dichiarazioni, definizioni e utilizzi delle variabili nel seguente ordine:

  1. meta
  2. events
  3. match (facoltativo)
  4. esito (facoltativo)
  5. condizione
  6. options (facoltativo)

Di seguito è riportata la struttura generica di una regola:

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

Commenti

Puoi contrassegnare i commenti con due barre (// comment) o con più righe utilizzando i caratteri asterisco (/* comment */), come faresti in C.

Costanti

Sono supportate le costanti numeriche, stringhe, booleane e numeri interi.

Costanti di stringa e regex

Puoi utilizzare uno dei seguenti caratteri di virgolette per racchiudere le stringhe in YARA-L 2.0. Tuttavia, il testo tra virgolette viene interpretato in modo diverso a seconda del testo utilizzato.

  1. Virgolette doppie (") - Vengono utilizzate per le stringhe normali. Deve contenere caratteri di escape.
    Ad esempio: "hello\tworld" —\t viene interpretato come una scheda

  2. Virgolette di ritorno (`): vengono usate per interpretare letteralmente tutti i caratteri.
    Ad esempio: "hello\tworld" - non viene interpretato come scheda

Per le espressioni regolari hai due opzioni.

Se vuoi utilizzare espressioni regolari direttamente senza la funzione re.regex(), utilizza /regex/ per le costanti delle espressioni regolari.

Puoi anche utilizzare costanti di stringa come costanti regex quando utilizzi la funzione re.regex(). Tieni presente che, per le costanti della stringa di virgolette doppie, devi eseguire l'escape dei caratteri barra rovesciata con caratteri barra rovesciata, che possono sembrare imbarazzanti.

Ad esempio, le seguenti espressioni regolari sono equivalenti:

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

Per agevolare la leggibilità, Google consiglia di utilizzare le virgolette precedenti per le stringhe nelle espressioni regolari.

Operatori

In YARA-L puoi utilizzare i seguenti operatori:

Operatore Descrizione
= uguale/dichiarazione
!= non uguale
< minore di
<= minore di o uguale a
> maggiore di
>= maggiore o uguale a

Variabili

In YARA-L 2.0, tutte le variabili sono rappresentate come $<variable name>.

Puoi definire i seguenti tipi di variabili:

  • Variabili evento: rappresentano gruppi di eventi in forma normalizzata (UDM) o eventi di entità. Specifica le condizioni per le variabili evento nella sezione events. Per identificare le variabili evento, utilizza i campi nome, origine evento e evento. Le origini consentite sono udm (per gli eventi normalizzati) e graph (per gli eventi delle entità). Se la sorgente viene omessa, udm viene impostata come fonte predefinita. I campi evento sono rappresentati come una catena di .<field name> (ad esempio, $e.field1.field2). Le catene di campi evento iniziano sempre dall'origine di primo livello (UDM o entità).

  • Variabili di corrispondenza: dichiara nella sezione match. Le variabili di corrispondenza diventano campi di raggruppamento per la query, in quanto viene restituita una riga per ogni insieme univoco di variabili di corrispondenza (e per ogni finestra temporale). Quando la regola trova una corrispondenza, vengono restituiti i valori della variabile di corrispondenza. Specifica ciò che ogni variabile di corrispondenza rappresenta nella sezione events.

  • Variabili segnaposto: dichiara e definisci nella sezione events. Le variabili segnaposto sono simili alle variabili di corrispondenza. Tuttavia, puoi utilizzare le variabili segnaposto nella sezione condition per specificare le condizioni di corrispondenza.

Utilizza le variabili di corrispondenza e le variabili segnaposto per dichiarare le relazioni tra i campi evento tramite condizioni di join transitive (per ulteriori dettagli, consulta la sezione Sintassi della sezione eventi).

Functions

Questa sezione descrive le funzioni di YARA-L 2.0 supportate da Chronicle in Motore di rilevamento.

Queste funzioni possono essere utilizzate nelle seguenti aree di una regola:

Funzioni di stringa

Chronicle supporta le seguenti funzioni di manipolazione delle stringhe:

  • strings.concat(a, b)
  • strings.to_lower(stringText)
  • string.to_upper(stringText)
  • string.base64_decode(codificaString)

Le seguenti sezioni descrivono come utilizzarle.

Concatena stringhe o numeri interi

Restituisce la concatenazione di due stringhe, due numeri interi o una combinazione dei due.

strings.concat(a, b)

Questa funzione accetta due argomenti, che possono essere stringhe o numeri interi e restituisce i due valori concatenati come stringa. I numeri interi vengono trasmessi a una stringa prima della concatenazione. Gli argomenti possono essere valori letterali o campi evento. Se entrambi gli argomenti sono campi, i due attributi devono provenire dallo stesso evento.

L'esempio seguente include una variabile stringa e un valore letterale stringa come argomenti.

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

L'esempio seguente include una variabile stringa e una variabile numero intero come argomenti. Sia entità.nome host e entità.port appartengono allo stesso evento, $e, e sono concatenati per restituire una stringa.

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

L'esempio seguente tenta di concatenare entità.port dall'evento $e1, con principal.host dall'evento $e2. Restituisce un errore di compilazione perché gli argomenti sono variabili di evento diverse.

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

Converti la stringa in lettere maiuscole o minuscole

Queste funzioni restituiscono il testo della stringa dopo aver modificato tutti i caratteri in maiuscolo o minuscolo.

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

Decodifica di una stringa Base64

Restituisce una stringa contenente la versione decodificata in base64 della stringa codificata.

strings.base64_decode(encodedString)

Questa funzione utilizza una stringa codificata in base64 come argomento. Se encodedString non è una stringa codificata base64 valida, la funzione restituisce encodedString così com'è.

Questo esempio restituisce True se il nome entità.domain.name è "dGVzdA=={quot;, ovvero la codifica base64 per la stringa "test".

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

Funzioni RegExp

Chronicle supporta le seguenti funzioni di espressione regolare:

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

Corrispondenza RegExp

Puoi definire la corrispondenza delle espressioni regolari in YARA-L 2.0 utilizzando una delle seguenti sintassi:

  • Utilizzo della sintassi YARA: correlato agli eventi. Di seguito è riportata una rappresentazione generica di questa sintassi: $e.field = /regex/
  • Utilizzo della sintassi YARA-L: come funzione che accetta i seguenti parametri:
    • Campo a cui viene applicata l'espressione regolare.
    • Espressione regolare specificata come stringa. Puoi utilizzare il modificatore nocase dopo le stringhe per indicare che la ricerca deve ignorare le lettere maiuscole. Di seguito è riportata una rappresentazione generica di questa sintassi: re.regex($e.field, `regex`)

Quando definisci le espressioni regolari in YARA-L 2.0, tieni presente quanto segue:

  • In entrambi i casi, il predicato è true se la stringa contiene una sottostringa che corrisponde all'espressione regolare fornita. Non è necessario aggiungere .* all'inizio o alla fine dell'espressione regolare.
  • Per far corrispondere la stringa esatta o solo un prefisso o un suffisso, includi l'anchor text ^ (iniziale) e $ (finale). Ad esempio, /^full$/ corrisponde esattamente a "full", mentre /full/ potrebbe corrispondere a "fullest", "lawfull" e "joyfully".
  • Se il campo UDM include caratteri di nuova riga, il carattere regexp corrisponde solo alla prima riga del campo UDM. Per applicare la corrispondenza completa dei campi UDM, aggiungi (?s) all'espressione regolare. Ad esempio, sostituisci /.*allUDM.*/ con /(?s).*allUDM.*/.

Acquisizione RegExp

Acquisisce (estrae) i dati da una stringa utilizzando il modello di espressione regolare fornito nell'argomento.

re.capture(stringText, regex)

Questa funzione prevede due argomenti:

  • stringText: la stringa originale da cercare.
  • regex: l'espressione regolare che indica il pattern da cercare.

L'espressione regolare può contenere 0 o 1 gruppo Capture tra parentesi. Se l'espressione regolare contiene 0 gruppi Capture, la funzione restituisce la prima sottostringa corrispondente. Se l'espressione regolare contiene 1 gruppo Capture, restituisce la prima sottostringa corrispondente per il gruppo Capture. La definizione di due o più gruppi di acquisizione restituisce un errore del compilatore.

In questo esempio, se $e.principal.hostname contiene "aaa1bbaa2" il seguente sarebbe True, perché la funzione restituisce la prima istanza. In questo esempio non sono presenti gruppi Capture.

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

Questo esempio illustra tutto ciò che segue il simbolo @ in un'email. Se il campo $e.network.email.from è test@google.com, l'esempio restituisce google.com. Questo esempio contiene un gruppo Capture.

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

Sostituzione RegExp

Esegue una sostituzione delle espressioni regolari.

re.replace(stringText, replaceRegex, replacementText)

Questa funzione prevede tre argomenti:

  • stringText: la stringa originale.
  • replaceRegex: l'espressione regolare che indica il pattern da cercare.
  • replaceText: il testo da inserire in ogni corrispondenza.

Restituisce una nuova stringa derivata dal stringa originale, in cui tutte le sottostringhe che corrispondono al pattern in replaceRegex vengono sostituite con il valore replacementText. Puoi utilizzare cifre con caratteri di escape (da \1 a \9) all'interno di replacementText per inserire del testo che corrisponda al gruppo tra parentesi corrispondente nel pattern replaceRegex. Utilizza \0 per fare riferimento all'intero testo corrispondente.

La funzione sostituisce le corrispondenze non sovrapposte e darà la priorità alla sostituzione della prima occorrenza trovata. Ad esempio, resostituisci("banana", "ana", "111") restituisce la stringa "b111na".

Questo esempio acquisisce tutto il testo dopo il simbolo @ in un'email, sostituisce com con org e quindi restituisce il risultato. Nota l'utilizzo di funzioni nidificate.

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

Questo esempio utilizza cifre con caratteri di escape nell'argomento replaceText per fare riferimento alle corrispondenze con il pattern 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"
                     )

Funzioni di data

Chronicle supporta le seguenti funzioni correlate alle date:

  • 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 supporta numeri interi negativi come argomento unix_secondi. I numeri interi rappresentati i tempi prima del periodo Unix. Se fornisci un numero intero non valido, ad esempio un valore che genera un overflow, la funzione restituirà -1. Si tratta di uno scenario insolito.

Poiché YARA-L 2 non supporta valori letterali interi negativi, assicurati di verificare questa condizione utilizzando l'operatore "minore o maggiore di". Ad esempio:

0 > timestamp.get_hour(123)

Estrazione temporale

Restituisce un numero intero compreso nell'intervallo [0, 59].

timestamp.get_minute(unix_seconds [, time_zone])

La funzione seguente restituisce un numero intero compreso nell'intervallo [0, 23], che rappresenta l'ora del giorno.

timestamp.get_hour(unix_seconds [, time_zone])

La funzione seguente restituisce un numero intero compreso nell'intervallo [1, 7] che rappresenta il giorno della settimana che inizia con domenica. Ad esempio, 1 = domenica; 2 = lunedì e così via.

timestamp.get_day_of_week(unix_seconds [, time_zone])

La funzione seguente restituisce un numero intero compreso nell'intervallo [0, 53] che rappresenta la settimana dell'anno. Le settimane iniziano di domenica. Le date precedenti alla prima domenica dell'anno sono nella settimana 0.

timestamp.get_week(unix_seconds [, time_zone])

Queste funzioni di estrazione temporale hanno gli stessi argomenti.

  • unix_seconds è un numero intero che rappresenta il numero di secondi successivi al periodo Unix, ad esempio $e.metadata.event_timestamp.seconds, o un segnaposto contenente quel valore.
  • time_zone è facoltativo ed è una stringa che rappresenta un time_zone. Se omessa, il valore predefinito è "GMT". Puoi specificare i fusi orari utilizzando i valori letterali di stringa. Le opzioni sono:
    • Il nome del database TZ, ad esempio "America/Los_Angeles". Per ulteriori informazioni, consulta la colonna "Nome database TZ" di questa pagina
    • La differenza di fuso orario rispetto a UTC, nel formato (+|-)H[H][:M[M]], ad esempio: "-08:00".

In questo esempio, l'argomento time_zone viene omesso, quindi viene impostato su "quot;GMT" per impostazione predefinita.

$ts = $e.metadata.collected_timestamp.seconds

timestamp.get_hour($ts) = 15

Questo esempio utilizza una stringa letterale di stringa per definire il fuso orario.

$ts = $e.metadata.collected_timestamp.seconds

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

Di seguito sono riportati alcuni esempi di specificatori del fuso orario validi, che puoi trasmettere come secondo argomento alle funzioni di estrazione temporale:

  • "America/Los_Angeles" o "-08:00". ("PST" non è supportato)
  • "America/New_York" o "-05:00". ("EST" non è supportato)
  • "Europe/London"
  • "UTC"
  • "GMT"

Timestamp corrente

Restituisce un numero intero che rappresenta l'ora corrente in secondi Unix. È approssimativamente uguale al timestamp di rilevamento e si basa sul momento in cui viene eseguita la regola.

timestamp.current_seconds()

L'esempio seguente restituisce True se il certificato è scaduto da più di 24 ore. Calcola la differenza di tempo sottraendo gli attuali secondi Unix e confrontando il risultato con un operatore maggiore di.

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

Funzioni matematiche

Valore assoluto

Restituisce il valore assoluto di un'espressione intera.

math.abs(intExpression)

Questo esempio restituisce True se gli eventi si sono verificati a più di cinque minuti di distanza, indipendentemente dall'evento che si è verificato per primo. Nota come l'esempio utilizza funzioni nidificate.

5 < timestamp.get_minute(
      math.abs($e1.metadata.event_timestamp.seconds
               - $e2.metadata.event_timestamp.seconds
      )
    )

Funzioni di rete

Restituisce true quando l'indirizzo IP fornito si trova all'interno della subnet specificata.

net.ip_in_range_cidr(ipAddress, subnetworkRange)

Puoi utilizzare YARA-L per cercare eventi UDM in tutti gli indirizzi IP all'interno di una subnet utilizzando l'istruzione net.ip_in_range_cidr(). Sono supportati sia IPv4 sia IPv6.

Per eseguire una ricerca in un intervallo di indirizzi IP, specifica un campo UDM IP e un intervallo CIDR (Classless Inter-Domain Routing). YARA-L può gestire entrambi i campi dell'indirizzo IP.

Esempio di IPv4:

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

Esempio di IPv6:

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

Per una regola di esempio che utilizza l'istruzione net.ip_in_range_cidr(), consulta la regola di esempio. Singolo evento in un intervallo di indirizzi IP

Funzione da assegnare a segnaposto

Puoi assegnare il risultato di una chiamata funzione a un segnaposto nella sezione events. Ad esempio:

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

Puoi quindi utilizzare le variabili segnaposto nelle sezioni match, condition e outcome. Esistono tuttavia due limitazioni relative alla funzione di assegnazione segnaposto:

  1. Ogni segnaposto nella funzione di assegnazione segnaposto deve essere assegnato a un'espressione contenente un campo evento. Ad esempio, i seguenti esempi sono validi:

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

    Tuttavia, l'esempio seguente non è valido:

    $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 chiamata a funzione deve dipendere da un unico evento. Tuttavia, è possibile utilizzare più di un campo dello stesso evento negli argomenti delle chiamate funzione. Ad esempio, quanto segue è valido:

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

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

    Tuttavia, quanto segue non è valido:

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

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

Sintassi della meta sezione

La sezione della meta è composta da più righe, dove ogni riga definisce una coppia chiave-valore. Una parte della chiave deve essere una stringa senza virgolette, mentre la parte relativa al valore deve essere una stringa tra virgolette:

<key> = "<value>"

Di seguito è riportato un esempio di riga di sezione meta valida: meta: author = "Chronicle" severity = "HIGH"

Sintassi della sezione Eventi

Nella sezione events, elenca i predicati per specificare quanto segue:

  • Che cosa rappresenta ogni variabile di corrispondenza o segnaposto
  • Espressioni binarie semplici come condizioni
  • Espressioni di funzione come condizioni
  • Espressioni elenco di riferimento come condizioni
  • Operatori logici

Dichiarazioni delle variabili

Per le dichiarazioni delle variabili, utilizza la seguente sintassi:

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

Entrambi sono equivalenti, come illustrato negli esempi seguenti:

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

Questa dichiarazione indica che questa variabile rappresenta il campo specificato per la variabile evento. Quando il campo evento è un campo ripetuto, la variabile di corrispondenza può rappresentare qualsiasi valore nell'array. È anche possibile assegnare più campi evento a una singola corrispondenza o variabile segnaposto. Si tratta di una condizione di unione transitiva.

Ad esempio, quanto segue:

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

Equivale a:

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

Quando viene utilizzata, una variabile deve essere dichiarata tramite dichiarazione di variabile. Se una variabile viene utilizzata senza dichiarazione, viene considerata come un errore di compilazione.

Espressioni binarie semplici come condizioni

Per utilizzare una semplice espressione binaria come condizione, utilizza la seguente sintassi:

  • <EXPR> <OP> <EXPR>

L'espressione può essere un campo di evento, una variabile, una costante o un'espressione di funzione.

Ad esempio:

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

Se entrambe le parti sono costanti, viene considerata un errore di compilazione.

Espressioni di funzione come condizioni

Alcune espressioni di funzione restituiscono un valore booleano che può essere utilizzato come singolo predicato nella sezione events. Tali funzioni sono:

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

Ad esempio:

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

Espressioni elenco di riferimento come condizioni

Utilizza l'operatore in per verificare l'esistenza di valori UDM in un elenco di riferimento basato sull'uguaglianza. L'operatore in può essere combinato con not per escludere i valori di un elenco di riferimento. Il nome dell'elenco di riferimento deve essere preceduto dal carattere %.

Al momento sono supportati solo i valori stringa:

  • $e.principal.hostname in %hostname_list
  • $e.about.ip in %phishing_site_list
  • $hostname in %whitelisted_hosts

Operatori logici

Puoi utilizzare gli operatori logici and e logici or nella sezione events, come mostrato negli esempi seguenti:

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

Per impostazione predefinita, l'ordine di precedenza dalla più alta alla più bassa è not, and, or.

Ad esempio, "a or b and c" è valutato come "a or (b and c)". Puoi utilizzare le parentesi per modificare la precedenza, se necessario.

Per impostazione predefinita, nella sezione events tutti i predicati sono considerati insieme insieme come AND.

Modificatori

case study

Quando hai un'espressione di confronto tra valori di stringa o un'espressione regex, puoi aggiungere maiuscole o minuscole alla fine dell'espressione per ignorare le maiuscole.

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

Non può essere utilizzato quando un tipo di campo è un valore enumerato. Gli esempi di seguito non sono validi e genereranno errori di compilazione:

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

Campi ripetuti

qualsiasi, tutti

In UDM ed Entità, alcuni campi sono etichettati come ripetuti, a indicare che si tratta di elenchi di valori o di altri tipi di messaggi. In YARA-L, ogni elemento nel campo ripetuto viene trattato singolarmente. Questo significa che se il campo viene utilizzato nella regola, la regola verrà valutata per ogni elemento del campo. Potrebbe verificarsi un comportamento imprevisto. Ad esempio, se una regola ha sia $e.principal.ip = "1.2.3.4" che $e.principal.ip = "5.6.7.8" nella sezione events, la regola non genera mai corrispondenze, anche se sia "1.2.3.4" sia "5.6.7.8" sono in principal.ip.

Per valutare il campo ripetuto nel suo complesso, puoi utilizzare gli operatori any e all. Quando viene utilizzato any, il predicato viene valutato come vero se un valore nel campo ripetuto soddisfa la condizione. Quando viene utilizzato all, il predicato viene valutato come vero se tutti i valori nel campo ripetuto soddisfano la condizione.

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

Gli operatori any e all possono essere utilizzati solo con campi ripetuti. Inoltre, non possono essere utilizzati quando si assegna un campo ripetuto a una variabile segnaposto o quando si unisce a un campo di un altro evento.

Ad esempio, any $e.principal.ip = $ip e any $e1.principal.ip = $e2.principal.ip non sono una sintassi valida. Per trovare una corrispondenza o uni un campo ripetuto, utilizza $e.principal.ip = $ip. Sarà presente un valore per la variabile di corrispondenza o un join per ogni elemento del campo ripetuto.

Quando scrivi una condizione con any o all, tieni presente che la modifica della condizione con not potrebbe non avere lo stesso significato dell'utilizzo dell'operatore negato.

Ad esempio:

  • not all $e.principal.ip = "192.168.12.16" verifica se non tutti gli indirizzi IP corrispondono a "192.168.12.16", ossia la regola sta verificando se un indirizzo IP non corrisponde a "192.168.12.16".
  • all $e.principal.ip != "192.168.12.16" verifica se tutti gli indirizzi IP non corrispondono a "192.168.12.16", ossia la regola verifica che nessun indirizzo IP corrisponda a "192.168.12.16".

Requisiti di unione delle variabili evento

Tutte le variabili evento utilizzate nella regola devono essere unite a qualsiasi altra variabile evento in uno dei seguenti modi:

  • direttamente tramite un confronto di uguaglianza tra i campi evento delle due variabili evento unite, ad esempio $e1.field = $e2.field. L'espressione non deve includere chiamate aritmetiche o di funzione.

  • indirettamente tramite un join transitivo che prevede solo un campo evento (consulta la dichiarazione variabile per la definizione di "join transitive"). L'espressione non deve includere chiamate aritmetiche o di funzione.

Ad esempio, se nella regola sono utilizzati $e1, $e2 e $e3, sono valide le seguenti sezioni events.

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

Tuttavia, ecco alcuni esempi di sezioni events non valide.

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

Sintassi della sezione delle corrispondenze

Nella sezione match, elenca le variabili di corrispondenza per gli eventi di gruppo prima di verificare le condizioni di corrispondenza. Questi campi vengono restituiti a ogni corrispondenza.

  • Specifica ciò che ogni variabile di corrispondenza rappresenta nella sezione events.
  • Specifica l'intervallo di tempo da utilizzare per mettere in relazione gli eventi dopo la parola chiave over. Gli eventi che non rientrano nell'intervallo di tempo vengono ignorati.
  • Per specificare l'intervallo di tempo, utilizza la seguente sintassi: <number><s/m/h/d> Dove s/m/h/d indica rispettivamente secondi, minuti, ore e giorni.
  • Puoi specificare almeno 1 minuto.
  • Puoi specificare un periodo massimo di 48 ore.

Di seguito è riportato un esempio di match valido:

$var1, $var2 over 5m

Questa istruzione restituisce $var1 e $var2 (definiti nella sezione events) quando la regola trova una corrispondenza. Il tempo specificato è di 5 minuti. Gli eventi che si trovano a più di 5 minuti di distanza non sono correlati e quindi ignorati dalla regola.

Ecco un altro esempio di match valido:

$user over 1h

Questa istruzione restituisce $user quando la regola trova una corrispondenza. La finestra temporale specificata è di 1 ora. Gli eventi che si trovano a più di un'ora di distanza non sono correlati. La regola non le considera rilevamento.

Ecco un altro esempio di match valido:

$source_ip, $target_ip, $hostname over 2m

Questa istruzione restituisce $source_ip, $target_ip e $hostname quando la regola trova una corrispondenza. L'intervallo di tempo specificato è di 2 minuti. Gli eventi che si trovano a più di due minuti di distanza non sono correlati. La regola non le considera rilevamento.

I seguenti esempi illustrano sezioni match non valide:

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

Finestra scorrevole

Per impostazione predefinita, le regole YARA-L 2.0 vengono valutate utilizzando le finestre di hop. Un intervallo di tempo dei dati relativi agli eventi aziendali è diviso in un insieme di finestre di hop sovrapposte, ciascuna con la durata specificata nella sezione match. Gli eventi sono quindi correlati in ogni finestra dell'hop. Con le finestre di hop, è impossibile cercare eventi che si verificano in un ordine specifico (ad esempio, e1 si verifica fino a due minuti dopo e2). Un'occorrenza di evento e1 e una occorrenza di evento e2 sono correlate a condizione che si verifichino entro la durata della finestra di hop.

Le regole possono essere valutate anche utilizzando finestre scorrevoli. Con le finestre scorrevoli, le finestre a scorrimento con la durata specificata nella sezione match vengono generate quando inizia o termina con una variabile evento pivot specificata. Gli eventi sono quindi correlati all'interno di ogni finestra scorrevole. Ciò rende possibile la ricerca di eventi che si verificano in un ordine specifico (ad esempio, e1 si verifica entro 2 minuti da e2). Un'occorrenza di evento e1 e un'occorrenza di evento e2 sono correlate se l'evento e1 si verifica entro la durata della finestra temporale successiva all'evento e2.

Specifica le finestre scorrevoli nella sezione match di una regola come segue:

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

La variabile evento pivot è la variabile evento su cui si basano le finestre scorrevoli. Se utilizzi la parola chiave before, vengono generate finestre scorrevoli che terminano con ogni occorrenza dell'evento pivot. Se viene utilizzata la parola chiave after, le finestre a scorrimento vengono generate a partire da ogni occorrenza dell'evento pivot.

Di seguito sono riportati alcuni esempi di utilizzi validi delle finestre a scorrimento:

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

Sintassi della sezione dei risultati

Nella sezione outcome puoi definire fino a 10 variabili dei risultati, con nomi arbitrari. Questi risultati verranno archiviati nei rilevamenti generati dalla regola. Ogni rilevamento può avere valori diversi per i risultati.

Il nome del risultato, $risk_score, è speciale. Facoltativamente, puoi definire un risultato con questo nome e, se lo fai, deve essere un tipo intero. Se completato, il risk_score verrà visualizzato nella vista Enterprise Insights per gli avvisi provenienti dal rilevamento delle regole.

Tipi di dati con variabili dei risultati

Ogni variabile di risultato può avere un tipo di dati diverso, determinato dall'espressione utilizzata per il calcolo. Sono supportati i seguenti tipi di dati sui risultati:

  • integer
  • string
  • elenchi di numeri interi
  • elenchi di stringhe

Logica condizionale

Puoi utilizzare la logica condizionale per calcolare il valore di un risultato. Le condizionali vengono specificate utilizzando il seguente pattern di sintassi:

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

Puoi leggere un'espressione condizionale come "if BOOL_CLAUSE è true, quindi restituisce THEN_CLAUSE, altrimenti restituisce ELSE_CLAUSE".

BOOL_CLAUSE deve restituire un valore booleano. Un'espressione BOOL_CLAUSE ha una forma simile a quella delle espressioni nella sezione events. Ad esempio, può contenere:

  • Nomi dei campi UDM con operatore di confronto, ad esempio:

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

  • una variabile segnaposto definita nella sezione events, ad esempio:

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

  • che restituiscono un valore booleano, ad esempio:

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

  • cercarlo in un elenco di riferimento, ad esempio:

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

THEN_CLAUSE e ELSE_CLAUSE devono essere dello stesso tipo di dati. Sono supportati numeri interi e stringhe.

Puoi omettere l'ELSE_CLAUSE se il tipo di dati è un numero intero. Se omesso, ELSE_CLAUSE restituisce 0. Ad esempio:

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

Devi fornire ELSE_CLAUSE se il tipo di dati è una stringa.

Operazioni matematiche

Puoi utilizzare operazioni matematiche per calcolare i risultati di tipi di dati interi. Supportiamo l'aggiunta e la sottrazione. Ad esempio:

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

Variabili segnaposto nei risultati

Durante il calcolo delle variabili dei risultati, puoi utilizzare le variabili segnaposto definite nella sezione Eventi della regola. In questo esempio, supponiamo che $email_sent_bytes sia stato definito nella sezione degli eventi della regola:

Esempio di evento singolo:

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

Esempio di evento multiplo:

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

Aggregazioni

La sezione dei risultati può essere utilizzata nelle regole per più eventi (regole che contengono una sezione delle corrispondenze) e nelle regole per un singolo evento (regole che non contengono una sezione delle corrispondenze). I requisiti per le aggregazioni sono i seguenti:

  • Regole per più eventi (con sezione delle corrispondenze)

    • L'espressione nei risultati di calcolo viene valutata in base a tutti gli eventi che hanno generato un determinato rilevamento.
    • L'espressione deve essere aggregata in una funzione aggregata
      • Esempio: $max_email_size = max($e.network.sent_bytes)
      • Se l'espressione contiene un campo ripetuto, l'aggregato opera su tutti gli elementi del campo ripetuto, su tutti gli eventi che hanno generato il rilevamento
  • Regole per eventi singoli (senza sezione delle corrispondenze)

    • L'espressione dei risultati di calcolo viene valutata rispetto al singolo evento che ha generato un determinato rilevamento.
    • Devi utilizzare la funzione aggregata per le espressioni che coinvolgono almeno un campo ripetuto
      • Esempio: $suspicious_ips = array($e.principal.ip)
      • L'aggregazione opera su tutti gli elementi nel campo ripetuto
    • Impossibile utilizzare la funzione di aggregazione per espressioni che non includono un campo ripetuto
      • Esempio: $threat_status = if($e.principal.file.size > 1024, "SEVERE", "MODERATE")

Puoi utilizzare le seguenti funzioni di aggregazione:

  • max(): restituisce il valore massimo fra tutti i valori possibili. Funziona solo con numeri interi.
  • min(): restituisce il minimo per tutti i valori possibili. Funziona solo con numeri interi.
  • sum(): restituisce la somma su tutti i valori possibili. Funziona solo con numeri interi.
  • count_distinct(): raccoglie tutti i valori possibili, poi genera il conteggio distinto dei valori possibili.
  • count(): si comporta come count_distinct(), ma restituisce un conteggio non distinto di valori possibili.
  • array_distinct(): raccoglie tutti i valori possibili, poi genera un elenco di questi valori. Tronca l'elenco dei valori a 25 elementi casuali.
  • array(): si comporta come array_distinct(), ma restituisce un elenco di valori non distinto. Tronca anche l'elenco dei valori a 25 elementi casuali.

La funzione aggregata è importante quando una regola include una sezione condition che specifica più eventi, in quanto la funzione aggregata funzionerà a tutti gli eventi che hanno generato il rilevamento.

Ad esempio, se le sezioni outcome e condition contengono:

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

Poiché la sezione della condizione richiede più di un event per ogni rilevamento, le funzioni aggregate funzioneranno su più eventi. Supponiamo che i seguenti eventi abbiano generato un rilevamento:

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

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

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

I valori dei risultati saranno quindi:

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

Informazioni importanti quando utilizzi la sezione dei risultati:

Altre note e limitazioni:

  • La sezione outcome non può fare riferimento a una nuova variabile segnaposto che non era già stata definita nella sezione events.
  • Allo stesso modo, la sezione outcome non può utilizzare eventi che non sono stati definiti nella sezione events
  • La sezione outcome può essere correlata solo agli eventi che sono già stati correlati nella sezione events

Puoi trovare un esempio utilizzando la sezione dei risultati in Panoramica di YARA-L 2.0. Consulta Creare analisi sensibili al contesto per i dettagli sul rilevamento di deduplicazioni con la sezione dei risultati.

Sintassi della sezione della condizione

Conteggio

Il carattere # è un carattere speciale nella sezione condition. Se è utilizzato prima di qualsiasi nome di evento o variabile segnaposto, rappresenta il numero di eventi o valori distinti che soddisfano tutte le condizioni della sezione events.

Syntax

Nella sezione condition, specifica la condizione di corrispondenza sopra gli eventi e le variabili definiti nella sezione events. Elenca i predicati di corrispondenza qui, uniti alla parola chiave and o or.

Le seguenti condizioni sono vincolate. Forza l'esistenza della variabile evento associata, il che significa che deve essere presente almeno un'occorrenza dell'evento in qualsiasi rilevamento.

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

Le seguenti condizioni non sono vincolanti. Consentono alla variabile evento associata di non esistere, il che potrebbe significare che l'evento non venga visualizzato in un rilevamento. Ciò rende possibile la creazione di regole inesistenti, che cercano l'assenza di una variabile anziché la presenza di una variabile.

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

Nell'esempio seguente, il carattere speciale # in una variabile (la variabile evento o la variabile segnaposto) rappresenta il conteggio di eventi o valori distinti di tale variabile:

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

Anche il seguente esempio di inesistenza può essere valido e restituisce true se ci sono più di due eventi distinti da $event1 e zero eventi distinti da $event2:

#event1 > 2 and !$event2

Di seguito sono riportati alcuni esempi di predicati non validi:

  • $e, #port > 50 // incorrect keyword usage
  • $e or #port < 50 // or keyword not supported with non-bounding conditions

Sintassi della sezione Opzioni

Nella sezione options, puoi specificare le opzioni per la regola. La sintassi per la sezione options è simile a quella della sezione meta. Tuttavia, una chiave deve essere uno dei nomi di opzioni predefiniti e il valore non è limitato al tipo di stringa.

Al momento, l'unica opzione disponibile è allow_zero_values.

  • allow_zero_value: se impostato su true, le corrispondenze generate dalla regola possono avere valori pari a zero come variabili con corrispondenza. I valori zero vengono assegnati ai campi evento quando non vengono compilati. Questa opzione è impostata su falso per impostazione predefinita.

Di seguito è riportata la riga della sezione options valida:

  • allow_zero_values = true

Controllo del tipo

Chronicle esegue il controllo del tipo in base alla sintassi YARA-L durante la creazione delle regole nell'interfaccia. Gli errori di controllo del tipo visualizzati ti consentono di rivedere la regola in modo che funzioni come previsto.

Di seguito sono riportati alcuni esempi di predicati non validi:

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