Problemi noti e limitazioni di YARA-L 2.0

Questo documento è destinato agli ingegneri del rilevamento che vogliono eseguire il debug della logica delle regole e ottimizzare l'esecuzione di YARA-L 2.0. Spiega come gestire i comportamenti non standard del motore, come l'estrazione dei campi, l'espansione del prodotto cartesiano nelle aggregazioni e la coerenza finale dell'arricchimento. Se segui questi metodi, puoi evitare errori logici che portano a valori dei risultati gonfiati o a rilevamenti mancati.

YARA-L 2.0 utilizza un modello di esecuzione specifico in cui i campi ripetuti vengono espansi in singole righe di eventi durante la valutazione. Poiché questa trasformazione avviene a livello di motore, il riferimento a più campi ripetuti o l'esecuzione di operazioni aritmetiche su tipi UDM non firmati richiedono soluzioni alternative di sintassi specifiche per evitare errori del compilatore o set di risultati errati. Questo documento descrive i vincoli tecnici e i pattern logici richiesti per risolverli.

Prima di iniziare

Prima di testare o modificare le regole YARA-L 2.0, assicurati che il tuo account disponga dei seguenti diritti tecnici:

Ruoli IAM richiesti

  • roles/chronicle.viewer (Visualizzatore operazioni di sicurezza): per visualizzare le regole esistenti e i metadati di rilevamento.
  • roles/chronicle.editor (Editor operazioni di sicurezza): per modificare la logica delle regole e salvare le modifiche.

Autorizzazioni obbligatorie

  • chronicle.rules.runTest: necessario per eseguire la funzionalità Esegui test sui dati storici.

  • chronicle.detections.get: per esaminare l'output degli eventi non nidificati nella dashboard di rilevamento.

Terminologia chiave

  • UDM (Unified Data Model): lo schema normalizzato utilizzato per strutturare tutta la telemetria di sicurezza inserita nella piattaforma.
  • Separazione:l'espansione a livello di motore di un singolo evento UDM contenente un campo ripetuto (array) in più righe. Ogni riga rappresenta un elemento univoco dell'array, il che può portare alla moltiplicazione delle righe durante la valutazione delle regole.
  • T₀ (esecuzione iniziale): la prima esecuzione di una regola sulla telemetria in entrata. Ciò si verifica durante la fase di "streaming", spesso prima che vengano finalizzati i processi di arricchimento in background (come gli aggiustamenti di GeoIP o ASN).

Aggregazioni dei risultati con l'estrazione dei campi ripetuti

Quando una regola fa riferimento a un campo ripetuto in una variabile evento con più elementi, ogni elemento viene suddiviso in una riga evento separata.

Ad esempio, i due indirizzi IP nel campo ripetuto target.ip dell'evento $e vengono suddivisi in due istanze di $e, ognuna con un valore target.ip diverso.

rule outbound_ip_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $outbound_ip_count = count($e.target.ip) // yields 2.

  condition:
    $e
}

Record di eventi: prima e dopo l'estrazione

Le tabelle in questa sezione mostrano come un singolo evento contenente un array di indirizzi IP viene trasformato in due record distinti.

Prima di annidare

La tabella seguente mostra il record evento prima dell'annidamento del campo ripetuto:

metadata.id principal.application target.ip
aaaaaaaaa Google SecOps [192.0.2.20, 192.0.2.28]

Dopo l'annidamento

La tabella seguente mostra il record evento dopo l'estrazione del campo ripetuto:

metadata.id principal.application target.ip
aaaaaaaaa Google SecOps 192.0.2.20
aaaaaaaaa Google SecOps 192.0.2.28

Campi ripetuti nidificati (prodotto cartesiano)

Quando una regola fa riferimento a un campo ripetuto nidificato all'interno di un altro, ad esempio security_results.action, l'annullamento della nidificazione avviene contemporaneamente a entrambi i livelli (principale e secondario). Il risultato è un prodotto cartesiano di tutti gli elementi.

Nell'esempio seguente, un evento $e con due valori ripetuti in security_results e due valori ripetuti in security_results.actions viene separato in quattro istanze.

rule security_action_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $security_action_count = count($e.security_results.actions) // yields 4.

  condition:
    $e
}

Record evento prima dell'annullamento del nesting

Il record originale memorizza le azioni all'interno di una struttura di array nidificata.

metadata.id principal.application security_results
aaaaaaaaa Google SecOps [ { actions: [ ALLOW, FAIL ] }, { actions: [ CHALLENGE, BLOCK ] } ]

Record di eventi dopo l'estrazione nidificata

Dopo l'espansione, ogni azione univoca diventa una riga separata, il che può portare a conteggi imprevisti nelle aggregazioni non distinte.

metadata.id principal.application security_results.actions
aaaaaaaaa Google SecOps CONSENTI
aaaaaaaaa Google SecOps ESITO NEGATIVO
aaaaaaaaa Google SecOps SFIDA
aaaaaaaaa Google SecOps BLOCCA

Impatto sui campi non correlati

Questo comportamento di annullamento del nesting nella valutazione delle regole può produrre aggregazioni di risultati impreviste quando la regola fa riferimento a uno o più campi ripetuti con un campo principale che è anche un campo ripetuto. Le aggregazioni non distinte come sum(), array() e count() non possono tenere conto dei valori duplicati di altri campi dello stesso evento prodotti dal comportamento di annidamento.

Nell'esempio seguente, l'evento $e ha un singolo nome host (google.com), ma il risultato (hostnames) aggrega quattro istanze non nidificate dello stesso evento $e, ognuna con un valore principal.hostname duplicato. Questo risultato produce quattro nomi host (anziché uno) a causa dell'annullamento dell'annidamento dei valori ripetuti in security_results.actions.

rule security_action_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $hostnames = array($e.principal.hostname) // yields 4.
    $security_action_count = count($e.security_results.action) // yields 4.

  condition:
    $e
}

Record evento prima dell'annidamento con campi non correlati

Il nome host è un valore singolo, ma si trova accanto ai risultati di sicurezza ripetuti.

metadata.id principal.application principal.hostname security_results
aaaaaaaaa Google SecOps google.com [ { action: [ ALLOW, FAIL ] }, { action: [ CHALLENGE, BLOCK ] } ]

Record evento dopo l'estrazione con campi non correlati

Il nome host ora è duplicato in quattro righe, il che fa sì che la funzione array() lo rilevi quattro volte.

metadata.id principal.application principal.hostname security_results.action
aaaaaaaaa Google SecOps google.com CONSENTI
aaaaaaaaa Google SecOps google.com ESITO NEGATIVO
aaaaaaaaa Google SecOps google.com SFIDA
aaaaaaaaa Google SecOps google.com BLOCCA

Soluzione alternativa per il comportamento di annullamento del nesting

Per assicurarti che i valori dei risultati siano accurati quando si verifica l'annidamento, utilizza la versione distinta dell'aggregazione selezionata. Le seguenti funzioni ignorano le righe duplicate create dall'estrazione:

  • max()
  • min()
  • array_distinct()
  • count_distinct()

Aggregazioni dei risultati con più variabili evento

Se una regola contiene più variabili evento, nell'aggregazione è presente un elemento separato per ogni combinazione di eventi inclusa nel rilevamento. Ad esempio, se la seguente regola di esempio viene eseguita in base agli eventi elencati:

events:
  $e1.field = $e2.field
  $e2.somefield = $ph

match:
  $ph over 1h

outcome:
   $some_outcome = sum(if($e1.otherfield = "value", 1, 0))

condition:
  $e1 and $e2
event1:
  // UDM event 1
  field="a"
  somefield="d"

event2:
  // UDM event 2
  field="b"
  somefield="d"

event3:
  // UDM event 3
  field="c"
  somefield="d"

La somma viene calcolata su ogni combinazione di eventi, consentendoti di utilizzare entrambe le variabili evento nei calcoli del valore del risultato. Nel calcolo vengono utilizzati i seguenti elementi:

1: $e1 = event1, $e2 = event2
2: $e1 = event1, $e2 = event3
3: $e1 = event2, $e2 = event1
4: $e1 = event2, $e2 = event3
5: $e1 = event3, $e2 = event1
5: $e1 = event3, $e2 = event2

Il risultato è una somma massima potenziale di 6, anche se $e2 può corrispondere solo a 3 eventi distinti.

Ciò influisce su somma, conteggio e matrice. Per conteggio e matrice, l'utilizzo di count_distinct o array_distinct può risolvere il problema, ma non esiste una soluzione alternativa per la somma.

Parentesi all'inizio di un'espressione

L'inizio di un'espressione con parentesi non è supportato e attiva un errore di analisi nell'editor delle regole.

Sintassi non valida

parsing: error with token: ")"
invalid operator in events predicate

Il seguente esempio genera questo tipo di errore:

($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600 > 1

Varianti di sintassi valide

Le seguenti varianti di sintassi restituiscono lo stesso risultato, ma con una sintassi valida:

$event.metadata.ingested_timestamp.seconds / 3600 -
$event.metadata.event_timestamp.seconds / 3600 > 1
    1 / 3600 * ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) > 1
    1 < ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600

L'array di indici nel risultato richiede l'aggregazione

L'indicizzazione diretta di un array all'interno della sezione outcome per i campi ripetuti non è consentita. Richiede una variabile segnaposto temporanea.

outcome:
  $principal_user_dept = $suspicious.principal.user.department[0]

Soluzione alternativa

Acquisisci l'indice dell'array specifico in una variabile segnaposto all'interno della sezione events, quindi fai riferimento a questo segnaposto nel risultato.

events:
  $principal_user_dept = $suspicious.principal.user.department[0]

outcome:
  $principal_user_department = $principal_user_dept

Condizione OR con non esistenza

Se applichi una condizione OR tra due variabili evento separate e se la regola corrisponde alla non esistenza, la regola viene compilata correttamente, ma può produrre rilevamenti di falsi positivi.

Ad esempio, la seguente sintassi della regola può corrispondere agli eventi con $event_a.field = "something" anche se non dovrebbe:

events:
     not ($event_a.field = "something" **or** $event_b.field = "something")
condition:
     $event_a and #event_b >= 0

Soluzione alternativa

Separa i controlli di non esistenza in blocchi individuali per ogni variabile per mantenere l'integrità della logica.

events:
  not ($event_a.field = "something")
  not ($event_b.field = "something")

condition:
  $event_a and #event_b >= 0

Aritmetica con campi evento non firmati

Se provi a utilizzare una costante intera in un'operazione aritmetica con un campo UDM il cui tipo è un numero intero senza segno, riceverai un errore. Ad esempio:

events:
  $total_bytes = $e.network.received_bytes * 2

Le costanti intere standard sono impostate per impostazione predefinita su numeri interi con segno, che non sono compatibili con i campi UDM definiti come numeri interi senza segno, come network.received_bytes.

Soluzione alternativa

Puoi aggirare questo errore forzando la costante intera a comportarsi come un numero in virgola mobile tramite un'operazione di divisione.

events:
  $total_bytes = $e.network.received_bytes * (2/1)

Arricchimento GeoIP e coerenza finale

Il sistema dà la priorità alla velocità rispetto all'accuratezza immediata nelle fasi di arricchimento iniziali (streaming e sensibilità alla latenza), il che può portare a dati mancanti e potenziali falsi positivi. Il sistema continua ad arricchire i dati in background, ma i dati potrebbero non essere disponibili quando viene eseguita la regola. Fa parte del normale processo di coerenza finale.

Per evitare falsi positivi causati dal ritardo dell'arricchimento, controlla esplicitamente che il campo non sia vuoto prima di valutarne il valore.

Ad esempio, considera questo evento regola:

$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"

La regola si basa sul fatto che l'evento deve avere $e.principal.ip_geo_artifact.network.asn = "16509" E $e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom", che sono entrambi campi arricchiti. Se l'arricchimento non viene completato in tempo, la regola genererà un falso positivo.

Per evitare questo problema, un controllo migliore per questa regola sarebbe:

$e.principal.ip_geo_artifact.network.asn != "" AND
$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region != "" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"

Questa regola elimina la possibilità che l'evento venga attivato da IP con ASN 16509 ma che si trovano al di fuori del Regno Unito. In questo modo, la precisione complessiva della regola migliora.

Scopri come risolvere i problemi relativi al ritardo dell'arricchimento.

Risoluzione dei problemi

Questa sezione descrive le aspettative di rendimento e fornisce soluzioni self-service per i problemi comuni in cui il comportamento del rilevamento live differisce dai risultati dei test.

Eventi futuri

Le regole multi-evento sono progettate per elaborare gli eventi in ordine cronologico rispetto all'importazione. Se specifichi e attivi una regola multi-evento, non vengono create rilevazioni per gli eventi con timestamp futuri, ad esempio quando event.timestamp ha una data e un'ora impostate dopo ingest.timestamp.

Ritardo dell'arricchimento

Google SecOps dà la priorità alla velocità di importazione per esporre gli avvisi iniziali il più rapidamente possibile. Tuttavia, i processi di arricchimento in background, come la risoluzione dei metadati GeoIP, ASN o UDM, seguono un modello di coerenza finale.

Esecuzione iniziale (T₀)

Il motore live potrebbe valutare una regola prima che l'arricchimento in background sia completato. A seconda che la logica si basi su campi arricchiti per rilevamenti o esclusioni, ciò può comportare le seguenti discrepanze temporanee:

  • Falsi negativi (ritardo nel rilevamento): questo è un risultato comune. Se una regola dipende da un campo arricchito per l'attivazione (ad esempio target.user.department == "Finance") e questo campo è null, la regola non corrisponde durante l'esecuzione iniziale.

  • Falsi positivi (mancata esclusione): se la regola utilizza campi arricchiti per filtrare l'attività nota come buona (ad esempio NOT target.ip_geo_country == "US"), la regola potrebbe attivare un falso positivo perché i dati di"esclusione" non sono ancora stati applicati.

Esecuzioni di adeguamento

Queste esecuzioni in background rivalutano i dati dopo un ritardo (ad esempio, 45 minuti o 30 ore). In questo modo, gli stati di rilevamento vengono "corretti" come segue:

  • Rilevamenti tardivi: gli eventi che erano "falsi negativi" al tempo T₀ ora producono un rilevamento una volta finalizzato l'arricchimento.

  • Correzione: tutti i falsi positivi T₀ rimangono nel sistema, ma i dati completamente arricchiti sono visibili nel visualizzatore UDM per la valutazione manuale.

Esegui test discrepanza

Lo strumento Esegui test opera sui dati storici già riconciliati. Poiché i dati sono completamente arricchiti al momento dell'esecuzione di un test manuale, puoi visualizzare immediatamente i risultati della "correzione". Ciò significa che non vedrai i falsi negativi T₀ o i falsi positivi basati sull'esclusione che si sono verificati durante l'esecuzione iniziale live.

Correzione degli errori

Utilizza la seguente tabella per risolvere le discrepanze tra gli avvisi in tempo reale e i risultati dei test.

Problema Descrizione Correzione attuabile
Errore di esclusione Una regola viene attivata nonostante un'esclusione (ad esempio, != "ASN_123") perché il campo era nullo durante l'esecuzione iniziale. Aggiungi un controllo not null alla sezione degli eventi per assicurarti che i dati vengano arricchiti prima della valutazione, ad esempio:

$e.principal.ip_geo_artifact.network.asn != ""
Partita reale rispetto alla partita di test Le regole attive attivano avvisi, ma Esegui test sugli stessi dati mostra "No Results". Aggiungi $e.field != "", che controlla tutti i campi arricchiti (GeoIP, ASN, File Path) per sincronizzare il comportamento in tempo reale e storico.
Metadati mancanti I rilevamenti vengono visualizzati nel pannello con i campi GeoIP o File Path vuoti. Questo è il comportamento previsto per le corse T0. Per risolvere il problema, includi un controllo field != "" o aumenta l'offset della prima esecuzione nella pianificazione dell'esecuzione per consentire più tempo per l'importazione.

Convalida e test

Per verificare che una regola gestisca correttamente l'arricchimento ritardato:

  1. Identifica il ritardo:individua un rilevamento che ritieni sia un falso positivo. Nella colonna Tipo di rilevamento, controlla la presenza dell'icona <span class="material-icons">lightbulb</span>. Gli avvisi senza questa icona provengono dall'esecuzione iniziale in cui il ritardo dell'arricchimento è più comune.

  2. Aggiorna la logica della regola:aggiungi un controllo field != "" per tutti i punti dati arricchiti utilizzati nella logica.
    Esempio (percorso file):
    $e.target.process.parent_process.file.full_path != ""

  3. Testa e verifica:

    • Utilizza la funzionalità Esegui test per assicurarti che la logica corrisponda ancora ai dati storici previsti.
    • Verifica che la regola venga attivata (o esclusa correttamente) solo durante le esecuzioni di adeguamento una volta compilati i campi di arricchimento.

Per maggiori dettagli, vedi Gestire la pianificazione di esecuzione delle regole e Configurare pianificazioni personalizzate per le regole.

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