Espressioni, operatori e altri costrutti

Supportato in:

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

Espressioni booleane

Le espressioni booleane sono espressioni di tipo booleano, che includono espressioni di confronto, espressioni di funzioni ed espressioni di elenchi di riferimenti 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 dei riferimenti o tabella 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 Utilizzare le tabelle di dati.

Esempio: sintassi per gli elenchi di riferimenti

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

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

Esempio: sintassi per le tabelle di dati

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

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 riferimento e tabelle di dati presenta le seguenti limitazioni:

  • Numero massimo di istruzioni in in una query, con o senza operatori speciali: 7
  • Massimo in istruzioni con l'operatore regex: 4
  • Massimo in istruzioni con l'operatore cidr: 2

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 dal più alto al più basso è not, and, or. Ad esempio, "a or b and c" viene valutato 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 nel seguente modo:

($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.

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 la distinzione tra maiuscole e minuscole in un'espressione di confronto tra valori 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 della barra obliqua per indicare un commento:

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

Valori letterali

YARA-L supporta numeri interi e virgola mobile non negativi, stringhe, valori booleani ed espressioni regolari letterali. 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 racchiusi tra virgolette doppie (") o virgolette inverse (`). La stringa viene interpretata in modo diverso, a seconda del tipo di virgolette utilizzato:

  • Virgolette doppie ("hello\tworld"): utilizzale per le stringhe normali; devono essere inclusi i caratteri di escape, dove \t viene interpretato come una 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.

Gli esempi seguenti 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/

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

Operatori

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

Variabili

In YARA-L, tutte le variabili utilizzano la sintassi $<variable name>. In YARA-L possono essere utilizzati i seguenti tipi di variabili.

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 evento sono udm (per gli eventi normalizzati) e graph (per gli eventi entità). Se la sorgente viene omessa, udm viene impostata come sorgente predefinita.

  • I campi evento 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

Le variabili segnaposto vengono utilizzate per acquisire e archiviare valori specifici dai campi evento UDM da utilizzare come riferimento in una query. Vengono utilizzati per collegare eventi disparati, 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.

Definisci le variabili segnaposto nella sezione events assegnando il valore di un campo UDM a un nome di variabile con il prefisso $ (ad esempio: $targetUser = $e.target.user.userid).

Puoi anche definire variabili segnaposto nelle seguenti sezioni:

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

Parole chiave

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 e 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 della query:
    • rule: avvia la definizione di una nuova query YARA-L.
    • private: contrassegna una query come privata, impedendone l'esposizione o l'attivazione diretta esterna.
    • global: contrassegna una query come globale, indicando che deve essere applicata in modo generico.
  • Sezioni della query:
    • meta: Introduce la sezione dei metadati per le informazioni descrittive sulla query.
    • strings: indica la sezione in cui sono definiti i pattern di stringa.
    • condition: specifica la sezione contenente la logica booleana per l'attivazione delle query.
    • events: definisce la sezione per specificare le variabili evento 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 combinare le condizioni.
    • all of, any of: utilizzati 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: verifica 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 mediante espressione regolare.
  • 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 le dimensioni del file in fase di analisi.
    • entrypoint: si riferisce al punto di ingresso di un eseguibile.

Maps

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

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

  • 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

Gli esempi riportati di seguito mostrano l'utilizzo valido e non valido delle mappe.

Utilizzo valido delle mappe

Utilizzare un campo Struct nella sezione degli 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 della 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

Combinare le parole chiave any o all con una mappa

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

Altri tipi di valori

La sintassi di Map può restituire solo un valore stringa. Nel caso di 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 gli interi.

Gestione dei valori duplicati nelle mappe

L'accesso alla mappa è destinato a recuperare un singolo valore associato a una chiave specifica. Si tratta di un 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 un elemento principale.

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 uniche, 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 eseguita 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 principale

Un campo ripetuto può 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 antenato

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

    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 loro 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 in base al suo indice o 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

Accedere a un risultato di 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 separa 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).

Accedere 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 separa 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 di tipo 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.