Espressioni, operatori e altri costrutti

Supportato in:

Questo documento include informazioni che ti aiutano a creare regole e query YARA-L utilizzando le espressioni.

Espressioni booleane

Le espressioni booleane sono espressioni con un tipo booleano, che include espressioni di confronto, espressioni di funzione ed espressioni di elenchi di riferimento o tabelle di dati. Puoi utilizzare espressioni booleane nelle sezioni events e outcome di una regola o query YARA-L.

Espressioni di confronto

Le espressioni di confronto sono espressioni che applicano un operatore di confronto a due espressioni. Le espressioni possono essere campi evento, variabili, valori letterali o espressioni di funzioni.

Esempio: espressioni di confronto

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

Espressioni di funzione

Alcune espressioni di funzione restituiscono un valore booleano, che può essere utilizzato come predicato individuale nella sezione events, ad esempio:

re.regex()

net.ip_in_range_cidr()

Esempio: espressioni di funzione

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

Elenco di riferimenti o tabella di dati

Puoi utilizzare elenchi di riferimento o tabelle di dati nelle sezioni events o outcome. Per saperne di più sul comportamento e sulla sintassi degli elenchi di riferimento e delle tabelle di dati, consulta Elenchi di riferimento e Utilizza le tabelle di dati.

Esempio: sintassi per gli elenchi di riferimento

I seguenti esempi mostrano la sintassi per vari tipi di elenchi di riferimento in una query:

// STRING reference list
$e.principal.hostname in %string_reference_list

// Regular expression reference list
$e.principal.hostname in regex %regex_reference_list

// CIDR reference list
$e.principal.ip in cidr %cidr_reference_list

Esempio: sintassi per le tabelle di dati

// STRING data table
$e.target.hostname in %data_table_name.column_name

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

Esempio: utilizzare not e nocase nella sintassi degli elenchi di riferimenti

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

L'operatore nocase è compatibile con gli elenchi STRING e REGEX.

Per motivi di prestazioni, l'utilizzo di elenchi di riferimenti e tabelle di dati presenta le seguenti limitazioni:

  • Numero massimo di istruzioni in in una query, con o senza operatori speciali: 10
  • Numero massimo di istruzioni in con l'operatore regex: 5
  • Numero massimo di istruzioni in con l'operatore cidr: 5

Espressioni logiche

Puoi utilizzare gli operatori logici and e or nella sezione events.

Esempio: espressioni logiche

$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" viene valutata come "a or (b and c)" quando gli operatori or e and sono definiti in modo esplicito nell'espressione.

Nella sezione events, i predicati vengono uniti utilizzando l'operatore and se non è definito esplicitamente un operatore. L'ordine di valutazione potrebbe essere diverso se l'operatore and è implicito nell'espressione. Considera le seguenti espressioni di confronto in cui or è definito in modo esplicito e l'operatore and è implicito.

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

Viene interpretato come segue:

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

Poiché or è definito in modo esplicito, i predicati circostanti vengono raggruppati e valutati per primi. L'ultimo predicato, $e2.field = "bar". viene unito implicitamente utilizzando and. Il risultato è che l'ordine di valutazione cambia.

Ricerca nelle tabelle di dati nelle espressioni logiche

Quando utilizzi le ricerche nelle tabelle dati (la sintassi in %list) all'interno della sezione events, si applicano i seguenti vincoli di sintassi:

  • Esclusività del tipo: non puoi combinare confronti di campi standard (ad esempio $field = "value") e ricerche di tabelle di dati all'interno dello stesso blocco logico.

  • Limitazione degli operatori: le ricerche nelle tabelle dati possono essere unite ad altre ricerche nelle tabelle dati solo utilizzando l'operatore OR. L'operatore AND non è supportato per queste espressioni.

  • Esclusività delle variabili evento con OR: quando utilizzi l'operatore OR per combinare le ricerche nelle tabelle di dati, tutte le ricerche all'interno dell'espressione OR devono fare riferimento a campi della stessa variabile evento. Ad esempio, ($e.user in %table1 OR $e.group in %table2) è valido. Tuttavia, espressioni come ($e.user in %table OR $g.user in %table) non sono supportate. Questo perché le ricerche in diverse variabili di evento (ad esempio $e e $g) in una condizione OR non hanno un'ancora di uguaglianza comune, il che causa l'errore del compilatore in fase di runtime con un RULE ERROR: error processing rule.

Esempio: risultati non validi in un errore di sintassi

// Invalid: Mixing a field comparison with a data table lookup
($field = "value" OR $field in %list)

// Invalid: Using AND with data table lookups
($field_A in %list_A AND $field_B in %list_B)

Esempio: esempio valido

// Valid: Multiple data table lookups joined by OR
($field in %list_A OR $field in %list_B)

Esempio: OR tra variabili non valido

// Invalid: OR condition across different event variables
($e.user in %table OR $g.user in %table)

Se la tua logica richiede sia un controllo del campo standard sia una ricerca nella tabella di dati, devi definirli come predicati separati e indipendenti all'interno della sezione events.

Tipi enumerati

Puoi utilizzare gli operatori con i tipi enumerati. Può essere applicato alle regole per semplificare e ottimizzare (utilizzare l'operatore anziché gli elenchi di riferimento) il rendimento.

Nell'esempio seguente, "USER_UNCATEGORIZED" e "USER_RESOURCE_DELETION" corrispondono a 15000 e 15014, quindi la regola cercherà tutti gli eventi elencati:

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

Modificatore Nocase

Per ignorare le maiuscole in un'espressione di confronto tra valori di stringa o un'espressione regolare, aggiungi nocase alla fine dell'espressione, come mostrato negli esempi seguenti.

Esempio: modificatore 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

Il modificatore nocase non può essere utilizzato quando il tipo di campo è un valore enumerato. I seguenti esempi non sono validi e genereranno errori di compilazione:

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

Commenti

I commenti possono essere utilizzati nelle query per fornire maggiori informazioni. Utilizzi il carattere barra obliqua per indicare un commento:

  • Per un commento di una sola riga, utilizza due barre oblique (// comment).
  • Per un commento su più righe, utilizza il carattere barra e l'asterisco (/* comment */).

Valori letterali

YARA-L supporta valori letterali interi e con virgola mobile non negativi, stringhe, valori booleani ed espressioni regolari. I valori letterali sono valori fissi utilizzati nelle condizioni delle query. YARA-L utilizza anche altri costrutti simili a valori letterali, come le espressioni regolari (racchiuse tra barre) per la corrispondenza dei pattern e i valori booleani (true/false) per la logica.

Valori letterali stringa

I valori letterali stringa sono sequenze di caratteri racchiuse tra virgolette doppie (") o apici inversi (`). La stringa viene interpretata in modo diverso, a seconda del tipo di virgolette utilizzato:

  • Doppi apici ("hello\tworld"): da utilizzare per le stringhe normali; devono essere inclusi i caratteri di escape, dove \t viene interpretato come tabulazione.
  • Apici inversi (`hello\tworld`): da utilizzare quando tutti i caratteri devono essere interpretati letteralmente, dove \t non viene interpretato come tabulazione.

Valori letterali delle espressioni regolari

Per i valori letterali delle espressioni regolari, hai due opzioni:

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

  • Se vuoi utilizzare i valori letterali stringa come valori letterali di espressioni regolari, utilizza la funzione re.regex(). Tieni presente che per i valori letterali stringa tra virgolette doppie, devi eseguire l'escape dei caratteri barra rovesciata con caratteri barra rovesciata, il che può sembrare strano.

I seguenti esempi mostrano espressioni regolari equivalenti:

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

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

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

Google consiglia di utilizzare i caratteri di apice inverso per le stringhe nelle espressioni regolari per una maggiore leggibilità.

Operatori

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

Informazioni sull'utilizzo delle variabili in YARA-L

In YARA-L, tutte le variabili utilizzano la sintassi $<variable name>. Questa sezione descrive i tipi di variabili da utilizzare in YARA-L.

Variabili evento

Le variabili evento rappresentano gruppi di eventi o eventi entità. Specifichi le condizioni per le variabili evento nella sezione events utilizzando un nome, l'origine evento e i campi evento.

  • Le origini eventi sono udm (per gli eventi normalizzati) e graph (per gli eventi entità). Se l'origine viene omessa, udm viene impostata come origine predefinita.

  • I campi degli eventi sono rappresentati come una catena di .<field name> (ad esempio, $e.field1.field2) e le catene di campi iniziano sempre dall'origine di primo livello (UDM o entità).

Variabili di corrispondenza

Le variabili di corrispondenza vengono utilizzate nella sezione match per raggruppare gli eventi in base a valori comuni in un intervallo di tempo specificato.

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 query trova una corrispondenza, vengono restituiti i valori delle variabili di corrispondenza.

Specifichi cosa rappresenta ogni variabile di corrispondenza nella sezione events.

Variabili segnaposto

Utilizzi le variabili segnaposto per acquisire e archiviare valori specifici dai campi evento UDM da fare riferimento e utilizzare in una query. Puoi utilizzarli per collegare eventi sparsi, soprattutto nelle query multi-evento. Assegnando un valore comune (ad esempio userid o hostname) a un segnaposto, puoi quindi utilizzarlo nella sezione match per raggruppare gli eventi che condividono quel valore in un intervallo di tempo specificato.

Puoi definire le variabili segnaposto nella sezione events assegnando il valore di un campo UDM a un nome di variabile preceduto da $ (ad esempio, $targetUser = $e.target.user.userid).

Puoi anche definire variabili segnaposto nelle seguenti sezioni:

  • Sezione condition per specificare le condizioni match.
  • outcome per eseguire calcoli, definire metriche o estrarre punti dati specifici dagli eventi corrispondenti.
  • Sezione match per raggruppare gli eventi in base a valori comuni.

Assegnazione della funzione al segnaposto

In YARA-L, l'assegnazione della funzione al segnaposto è il processo di trasformazione dei dati degli eventi UDM e di archiviazione del risultato per l'utilizzo in una regola. Questa azione ti consente di eseguire calcoli o manipolazioni dei dati nella sezione events e di fare riferimento ai risultati nelle sezioni match, condition e outcome.

Di seguito sono riportati i componenti principali:

  • Funzioni: operazioni integrate che eseguono calcoli o trasformazioni dei dati (ad esempio manipolazione di stringhe o operazioni matematiche) su campi evento specifici.
  • Variabili segnaposto: variabili definite dall'utente, con il prefisso $ (ad esempio, $user, $ip), che fungono da contenitori. Memorizzano i valori estratti direttamente dagli eventi o generati dagli output delle funzioni.
  • Assegnazione: la logica che collega l'output di una funzione a una variabile segnaposto, rendendo i dati trasformati accessibili al resto della logica di rilevamento.

Limitazioni

Esistono due limitazioni quando si utilizza un'assegnazione da funzione a segnaposto:

  1. Devi assegnare ogni segnaposto a un'espressione che contenga un campo evento.

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

    Esempio 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 di funzione deve dipendere da esattamente un evento. Tuttavia, negli argomenti della chiamata di funzione è possibile utilizzare più di un campo dello stesso evento.

    Esempio valido

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

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

    Esempio non valido

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

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

Utilizza le parole chiave per definire le query

In YARA-L, le parole chiave sono parole riservate che definiscono la struttura e la logica di una query di rilevamento. Vengono utilizzati per specificare diverse sezioni di una query, eseguire operazioni logiche e matematiche e definire le condizioni per la corrispondenza degli eventi. Queste parole chiave non possono essere utilizzate come identificatori per query, stringhe o variabili.

Le parole chiave non sono sensibili alle maiuscole (ad esempio, and o AND sono equivalenti).

Categorie principali di parole chiave YARA-L 2.0

Questo elenco non è esaustivo, ma copre le parole chiave principali utilizzate in YARA-L 2.0 per creare query di rilevamento efficaci.

  • Definizione di query:
    • rule: avvia la definizione di una nuova query YARA-L.
    • private: designa una query come privata, impedendone l'esposizione diretta o l'attivazione esterna.
    • global: contrassegna una query come globale, indicando che deve essere applicata in modo generico.
  • Sezioni delle query:
    • meta: introduce la sezione dei metadati per le informazioni descrittive sulla query.
    • strings: indica la sezione in cui sono definiti i pattern di stringhe.
    • condition: specifica la sezione contenente la logica booleana per l'attivazione delle query.
    • events: definisce la sezione per specificare le variabili degli eventi e le relative condizioni.
    • match: introduce la sezione per l'aggregazione dei valori in un intervallo di tempo.
    • outcome: definisce la sezione per l'aggiunta di contesto e punteggio alle query attivate.
  • Modificatori di stringa:
    • ascii: specifica che una stringa deve essere abbinata come testo ASCII.
    • wide: indica che una stringa deve essere abbinata come caratteri estesi (UTF-16).
    • nocase: Esegue una corrispondenza di stringhe senza distinzione tra maiuscole e minuscole.
    • fullword: richiede che la stringa corrisponda a una parola completa.
    • xor: applica la trasformazione XOR alla stringa prima della corrispondenza.
    • base64, base64wide: applica la codifica Base64 prima della corrispondenza.
  • Operatori logici:
    • and, or, not: operatori logici booleani standard per la combinazione di condizioni.
    • all of, any of: utilizzato per valutare più espressioni all'interno di una condizione.
  • Operatori di confronto e relazionali:
    • at: specifica un offset esatto per la corrispondenza delle stringhe.
    • contains: Controlla se una stringa contiene una sottostringa.
    • startswith, endswith: controlla se una stringa inizia o termina con una sottostringa.
    • icontains, istartswith, iendswith, iequals: versioni senza distinzione tra maiuscole e minuscole.
    • matches: utilizzato per la corrispondenza delle espressioni regolari.
  • Tipi di dati e specificatori di dimensioni:
    • int8, uint8, int16, uint16, int32, uint32: tipi di numeri interi con dimensioni specificate.
    • int8be, uint8be, int16be, uint16be, int32be, uint32be: versioni big-endian dei tipi di numeri interi.
    • filesize: rappresenta la dimensione del file in fase di analisi.
    • entrypoint: Si riferisce all'entry point di un eseguibile.

Supporto delle mappe YARA-L

YARA-L supporta le mappe per i tipi di dati Struct e Label, utilizzati in alcuni campi UDM.

Per cercare una coppia chiave-valore specifica nei tipi di dati Struct e Label, utilizza la sintassi standard della mappa:

  • Sintassi del campo Struct: $e.udm.additional.fields["pod_name"] = "kube-scheduler"
  • Sintassi del campo dell'etichetta: $e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"

Esempio: utilizzo valido e non valido delle mappe

I seguenti esempi mostrano un utilizzo valido e non valido delle mappe.

Utilizzo valido delle mappe

Utilizzo di un campo Struct nella sezione Eventi:

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

Utilizzo di un campo Etichetta nella sezione Risultato:

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

Assegnare un valore della mappa a un segnaposto:

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

Utilizzo di un campo mappa in una condizione di join:

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

Utilizzo non supportato delle mappe

Combinazione di parole chiave any o all con una mappa

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

Altri tipi di valori

La sintassi Map può restituire solo un valore stringa. Nel caso dei tipi di dati [Struct](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#struct), la sintassi della mappa può accedere solo alle chiavi i cui valori sono stringhe. Non è possibile accedere alle chiavi i cui valori sono altri tipi primitivi, come i numeri interi.

Gestione dei valori duplicati nelle mappe

L'accesso alla mappa è destinato a recuperare un singolo valore associato a una chiave specifica. Questo è il comportamento standard e previsto. Tuttavia, in situazioni rare e insolite, il contesto di map access potrebbe puntare inavvertitamente a più valori. Nel raro caso limite in cui l'accesso alla mappa si riferisce a più valori, map access restituirà in modo deterministico il primo valore. Ciò può accadere se un'etichetta ha una chiave duplicata o un campo ripetuto di antenati.

L'etichetta ha una chiave duplicata

La struttura dell'etichetta rappresenta una mappa, ma non impone l'unicità della chiave. Per convenzione, una mappa deve avere chiavi univoche, pertanto Google SecOps non consiglia di compilare un'etichetta con chiavi duplicate.

Esempio: etichetta con chiave duplicata

Il testo della query $e.metadata.ingestion_labels["dupe-key"] restituirebbe il primo valore possibile, val1, se eseguito sull'esempio di dati seguente:

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

L'etichetta ha un campo ripetuto predecessore

Un campo ripetuto potrebbe contenere un'etichetta come campo secondario. Due voci diverse nel campo ripetuto di primo livello potrebbero contenere etichette con la stessa chiave.

Esempio: etichetta con campo ripetuto predecessore

Il testo della query $e.security_result.rule_labels["key"] restituirebbe il primo valore possibile, "val3", se eseguito sul seguente esempio di dati:

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

Accedere alle variabili di risultato nelle mappe

Questa sezione spiega come accedere alle variabili di risultato all'interno delle mappe con i relativi tipi di dati originali (ad esempio numeri interi, valori booleani o elenchi di questi tipi) anziché solo stringhe. Puoi utilizzare questa funzionalità per una maggiore flessibilità e precisione per la logica della query.

I dati sugli esiti sono disponibili nei seguenti campi:

  • I valori dei risultati mantengono i tipi originali nel campo variables.
  • Il campo outcomes memorizza le versioni string per la compatibilità con le versioni precedenti.

Puoi accedere a questi valori di risultato utilizzando la mappa variables per recuperare il tipo specifico o accedere agli elementi in una sequenza utilizzando l'indicizzazione degli array. Puoi accedere a un elemento specifico della sequenza tramite il relativo indice oppure selezionare l'intera sequenza per valutare ogni valore singolarmente.

Sintassi:

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

Sintassi per le sequenze:

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

Esempi: variabili di risultato dell'accesso nelle mappe

Accedi a un risultato di tipo stringa:

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

Questo esempio recupera direttamente il valore della stringa (ad esempio, "1.1.1.1" se outcome_ip fosse una singola stringa).

Accedere a un risultato intero

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

Questo esempio recupera il valore intero (ad esempio, 30).

Accedere a un elenco di numeri interi utilizzando Int64Sequence

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

Questo esempio recupera l'elenco completo di numeri interi e li unisce come campi ripetuti (ad esempio [2, 3, 4]).

Accedere a un elemento specifico da un elenco di numeri interi

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

Questo esempio recupera il primo numero intero dall'elenco (ad esempio, 2).

Accedi a un elenco di stringhe (StringSequence)

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

Questo esempio recupera l'elenco completo delle stringhe e le unnest come campi ripetuti (ad esempio ["1.1.1.1", "2.2.2.2"]).

Accedere a un elemento specifico da un elenco di stringhe

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

Questo esempio recupera il primo indirizzo IP dall'elenco (ad esempio, "1.1.1.1").

Suffissi dei tipi disponibili per variables

Per un elenco completo dei suffissi supportati, consulta FindingVariable.

Hai bisogno di ulteriore assistenza? Ricevi risposte dai membri della community e dai professionisti di Google SecOps.