Problemi noti di YARA-L 2.0

Questo documento è destinato agli ingegneri di 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'annidamento dei campi, l'espansione del prodotto cartesiano nelle aggregazioni e la coerenza finale dell'arricchimento. Seguendo questi metodi, puoi evitare errori di logica che portano a valori di risultato 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 sui tipi UDM senza segno richiedono soluzioni alternative di sintassi specifiche per evitare errori del compilatore o set di risultati errati. Questo documento illustra questi 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 di Security Operations): per visualizzare le regole esistenti e i metadati di rilevamento.
  • roles/chronicle.editor (editor di Security Operations): per modificare la logica delle regole e salvare le modifiche.

Autorizzazioni obbligatorie

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

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

Terminologia chiave

  • UDM (Unified Data Model): lo schema normalizzato utilizzato per strutturare tutti i dati di telemetria di sicurezza importati sulla piattaforma.
  • Annidamento: 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, che può portare alla moltiplicazione delle righe durante la valutazione delle regole.
  • T₀ (esecuzione iniziale): la prima esecuzione di una regola sui dati di telemetria in entrata. Si verifica durante la fase di "streaming", spesso prima che i processi di arricchimento in background (come gli allineamenti GeoIP o ASN) vengano finalizzati.

Aggregazioni dei risultati con l'annidamento 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 di 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'annidamento

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

Prima dell'annidamento

La tabella seguente mostra il record di eventi 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 di eventi dopo l'annidamento 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, come security_results.action, l'annidamento si verifica 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 vengono annidati 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 di eventi prima dell'annidamento nidificato

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'annidamento nidificato

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 annidamento 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 in 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 le quattro istanze non annidate dello stesso evento $e, ognuna con un valore principal.hostname duplicato. Questo risultato genera quattro nomi host (anziché uno) a causa 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 di eventi prima dell'annidamento con campi non correlati

Il nome host è un singolo valore, 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 di eventi dopo l'annidamento 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 annidamento

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'annidamento:

  • 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 sugli 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 dei valori dei risultati. 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.

Questo influisce su somma, conteggio e array. Per conteggio e array, 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 le 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 a 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 senza segno

Se provi a utilizzare una costante intera in un'operazione aritmetica con un campo UDM il cui tipo è un 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 interi con segno, che non sono compatibili con i campi UDM definiti come interi senza segno, come network.received_bytes.

Soluzione alternativa

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

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

Arricchimento GeoIP e coerenza finale

Nelle fasi di arricchimento iniziali (streaming e sensibili alla latenza), il sistema dà la priorità alla velocità rispetto all'accuratezza immediata, il che può portare alla perdita di dati e a 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 di 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 produrrà 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 indirizzi IP con l'ASN 16509, ma situati al di fuori del Regno Unito. In questo modo, la precisione complessiva della regola viene migliorata.

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

Risoluzione dei problemi

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

Eventi con data futura

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 creati rilevamenti 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 Security Operations dà la priorità alla velocità di importazione per mostrare 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 i rilevamenti o le esclusioni, ciò può portare alle seguenti discrepanze temporanee:

  • Falsi negativi (ritardo di 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 (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 allineamento

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 "allineati" come segue:

  • Rilevamenti tardivi: gli eventi che erano "falsi negativi" in 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.

Discrepanza del test di esecuzione

Lo strumento Esegui test opera sui dati storici che sono già stati riconciliati. Poiché i dati sono completamente arricchiti quando esegui un test manuale, puoi vedere immediatamente i risultati dell'"allineamento". 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 live e i risultati dei test.

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

$e.principal.ip_geo_artifact.network.asn != ""
Corrispondenza live rispetto al test Le regole live attivano gli 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 live e storico.
Metadati mancanti I rilevamenti vengono visualizzati nella dashboard con i campi GeoIP o File Path vuoti. Questo è il comportamento previsto per le esecuzioni 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 l'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 delle regole: 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 allineamento una volta compilati i campi di arricchimento.

Per maggiori dettagli, consulta Gestisci la pianificazione dell'esecuzione delle regole e Configura pianificazioni personalizzate per le regole.

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