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:
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.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 != ""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.