Regole per eventi singoli e multipli in YARA-L

Supportato in:

Questo documento mostra le query scritte in YARA-L 2.0. Ogni esempio mostra come correlare gli eventi all'interno del linguaggio delle regole di query per identificare le minacce alla sicurezza, monitorare il comportamento delle entità e arricchire i rilevamenti con la logica di business.

Utilizza gli esempi come elementi di base di YARA-L 2.0, tra cui il rilevamento di singoli eventi, la corrispondenza di espressioni regolari e il filtro degli intervalli di rete. Questi esempi sono organizzati in categorie funzionali per aiutarti a passare dalla logica di base alla correlazione avanzata di più eventi e ai rilevamenti compositi.

Sintassi di base

Gli esempi in questa sezione mostrano come correlare efficacemente gli eventi UDM e strutturare le query all'interno del linguaggio delle regole.

Argomento Esempi
Query su un singolo evento Ricerca iniziale dell'accesso utente; Rilevamento dell'accesso di 5 minuti
Query e ottimizzazione Rilevamento dei processi basato sull'esclusione
Intervallo e logica di rete Corrispondenza di un singolo evento (intervallo IP)
Espressioni regolari nelle query Filtro email; Espressione regolare del nome host; Ricerca log non elaborati
Campi ripetuti con condizioni universali Convalida dell'IP di accesso sospetto

Query per evento singolo

Caso d'uso: rilevamento di base di un tipo di evento specifico (ad esempio USER_LOGIN) senza necessità di correlazione in un intervallo di tempo.

Logica chiave: utilizza solo le sezioni degli eventi e delle condizioni per identificare una singola occorrenza. Una regola per eventi singoli può essere:

  • Qualsiasi regola senza una sezione match.
  • Regola con una sezione match e una sezione condition che controlla solo l'esistenza di un evento (ad esempio $e, #e > 0, #e >= 1, 1 <= #e, 0 < #e).

Regola

Il seguente esempio di regola cerca un evento di accesso utente (USER_LOGIN) e restituisce il primo che incontra nei datastore aziendali memorizzati nel tuo account Google SecOps:

rule SingleEventRule {
meta:
  author = "noone@altostrat.com"

events:
  $e.metadata.event_type = "USER_LOGIN"

condition:
  $e
}

Questo esempio di ricerca non aggregata restituisce direttamente i singoli eventi. Poiché questa query non richiede la correlazione degli eventi, le variabili evento, come $e1, vengono omesse.

metadata.event_type = "USER_LOGIN"

Dashboard

Poiché questa logica di query si concentra sulla visualizzazione di eventi specifici e non correlati nel loro stato non elaborato, non utilizza le sezioni match o outcome richieste per le visualizzazioni della dashboard.

Esempio: rilevamento dell'accesso in cinque minuti

Regola

Il seguente esempio mostra una regola basata su un singolo evento che utilizza la sezione match per trovare qualsiasi utente con almeno un evento di accesso che si verifica in un intervallo di tempo di 5 minuti (5m). Verifica l'esistenza di un evento di accesso utente.

rule SingleEventRule {
meta:
  author = "alice@example.com"
  description = "windowed single event example rule"

events:
  $e.metadata.event_type = "USER_LOGIN"
  $e.principal.user.userid = $user

match:
  $user over 5m

condition:
  #e > 0
}

Cerca

Questo esempio di ricerca statistica aggrega l'attività in finestre a cascata di cinque minuti (5m), con un output di una riga per utente per finestra. Poiché la query si concentra sui conteggi volumetrici per finestra, le variabili event e le sezioni condition vengono omesse, in quanto i risultati includono intrinsecamente uno o più eventi. Questa versione utilizza una finestra a cascata anziché una finestra di hopping per garantire che i risultati vengano visualizzati correttamente all'interno della piattaforma.

metadata.event_type = "USER_LOGIN"
principal.user.userid = $user

match:
  $user by 5m

Dashboard

L'esempio seguente incorpora una sezione outcome per calcolare il conteggio totale degli eventi per utente, il che aiuta a tracciare i dati come valore statistico nel tempo. La query utilizza una finestra a cascata anziché una finestra di hopping per assicurarsi che i punti dati vengano mappati a bucket discreti e non sovrapposti e fornisce una visualizzazione più chiara per le tendenze della dashboard.

metadata.event_type = "USER_LOGIN"
principal.user.userid = $user

match:
  $user by 5m

outcome:
  $event_count = count(metadata.id)

Esecuzione di query e ottimizzazione

Caso d'uso: rileva le finestre di Windows svchost.exeche vengono avviate da directory non standard.

Logica della chiave: negazione (not) combinata con la corrispondenza mediante espressione regolare.

Esempio: rilevamento dei processi basato sull'esclusione

Regola

La seguente regola verifica la presenza di pattern specifici nei dati sugli eventi e crea un rilevamento se li trova. Questa regola include una variabile $e1 per il monitoraggio del tipo di evento e un campo UDM metadata.event_type. La regola verifica la presenza di occorrenze specifiche di corrispondenze di espressioni regolari con e1. Quando si verifica l'evento $e1, viene creata una rilevazione. Nella regola è inclusa una condizione not per escludere determinati percorsi non dannosi. Puoi aggiungere not condizioni per evitare falsi positivi.

rule suspicious_unusual_location_svchost_execution
{
meta:
  author = "Google Cloud Security"
  description = "Windows 'svchost' executed from an unusual location"
  yara_version = "YL2.0"
  rule_version = "1.0"

events:
  $e1.metadata.event_type = "PROCESS_LAUNCH"
  re.regex($e1.principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
  not re.regex($e1.principal.process.command_line, `\\Windows\\System32\\`) nocase

condition:
  $e1
}

Cerca

Questo esempio esegue una ricerca non aggregata per restituire singoli eventi. Poiché questa ricerca non richiede la correlazione degli eventi in più istanze, le variabili evento come $e1 non sono necessarie.

metadata.event_type = "PROCESS_LAUNCH"
re.regex(principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
not re.regex(principal.process.command_line, `\\Windows\\System32\\`) nocase

Dashboard

Questa sintassi incorpora le sezioni match e outcome per calcolare il volume degli eventi nel tempo. La funzione timestamp.get_timestamp() raggruppa i risultati per giorno per la visualizzazione delle tendenze.

metadata.event_type = "PROCESS_LAUNCH"
re.regex(principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
not re.regex(principal.process.command_line, `\\Windows\\System32\\`) nocase
$date = timestamp.get_timestamp(metadata.event_timestamp.seconds)

match:
  $date

outcome:
  $event_count = count(metadata.id)

Intervallo e logica di rete

Caso d'uso: filtra l'attività in base a subnet IP specifiche (CIDR) e alla corrispondenza con più nomi host possibili.

Logica chiave: utilizza la funzione net.ip_in_range_cidr() per la corrispondenza delle subnet e l'operatore OR per il controllo rispetto a più nomi host possibili.

  • net.ip_in_range_cidr(): questa funzione verifica se un determinato indirizzo IP è contenuto in una determinata subnet CIDR (Classless Inter-Domain Routing).
  • Operatore logico OR: utilizzato per combinare più condizioni. Le condizioni all'interno della sezione dell'evento vengono combinate implicitamente con AND. L'operatore OR esegue il controllo su più nomi host possibili.

Esempio: corrispondenza di un singolo evento (intervallo IP)

Regola

L'esempio seguente mostra una regola per un singolo evento che cerca corrispondenze tra due nomi host specifici e un intervallo specifico di indirizzi IP:

rule OrsAndNetworkRange {
meta:
  author = "noone@altostrat.com"

events:
  // Checks CIDR ranges.
  net.ip_in_range_cidr($e.principal.ip, "203.0.113.0/24")

  // Detection when the hostname field matches either value using or.
  $e.principal.hostname = /pbateman/ or $e.principal.hostname = /sspade/

condition:
  $e
}

Cerca

Il seguente esempio di query identifica gli eventi in cui un indirizzo IP specifico rientra in un intervallo CIDR definito e il nome host corrisponde a un pattern utente specifico:

net.ip_in_range_cidr(principal.ip, "203.0.113.0/24")

principal.hostname = /pbateman/ or principal.hostname = /sspade/

Poiché si tratta di una query di ricerca, non di una regola di rilevamento, l'intero evento viene restituito automaticamente se i filtri sono soddisfatti. Una sezione match raggruppa i dati per principal.ip e principal.hostname. Una sezione condition non è obbligatoria e le variabili evento ($e) vengono omesse perché non viene eseguita alcuna correlazione degli eventi.

Dashboard

La seguente query di esempio aggrega i risultati raggruppando le coppie di IP e nome host univoci:

net.ip_in_range_cidr(principal.ip, "203.0.113.0/24")

principal.hostname = /pbateman/ or principal.hostname = /sspade/

match:
  principal.ip, principal.hostname

Espressioni regolari nelle query

Caso d'uso: cerca pattern di stringhe flessibili (ad esempio, domini specifici nelle email) ignorando le lettere maiuscole. Questo è di uso comune nella ricerca e nelle regole.

Logica chiave: utilizza /regex/ nocase per le corrispondenze di base e la funzione re.regex() per l'analisi dei campi complessi.

Esempio: filtro email

Regola

Il seguente esempio di espressione regolare YARA-L 2.0 cerca eventi con email ricevute dal dominio altostrat.com. Poiché nocase è stato aggiunto al confronto tra variabili $host regex e alla funzione regex, questi confronti non fanno distinzione tra maiuscole e minuscole.

rule RegexRuleExample {
meta:
  author = "noone@altostrat.com"

events:
  $e.principal.hostname = $host
  $host = /.*HoSt.*/ nocase
  re.regex($e.network.email.from, `.*altostrat\.com`) nocase

match:
  $host over 10m

condition:
  #e > 10
}

Cerca

Nell'interfaccia di ricerca, questa logica viene utilizzata per il rilevamento delle minacce ad alta fedeltà e l'esplorazione dei dati. Anziché attendere un avviso automatico, gli analisti possono eseguire manualmente query sull'UDM per individuare istanze specifiche di nomi host corrispondenti a una convenzione di denominazione insieme a domini email mirati. Questo è il metodo principale per convalidare il volume di questi eventi prima di promuoverli in una regola di rilevamento persistente.

principal.hostname = $host
$host = /.*HoSt.*/ nocase
re.regex(network.email.from, `.*altostrat\.com`) nocase
match:
 $host over 10m

Dashboard

La seguente logica identifica i pattern di interesse aggregando la telemetria hostname e email in bucket di 10 minuti (10m). Se utilizzata in una dashboard, questa logica consente agli analisti di visualizzare la frequenza di comunicazione da asset specifici (corrispondenti a host) al dominio altostrat.com. Questa visualizzazione è essenziale per monitorare le tendenze di movimento dei dati interni e identificare i principali comunicatori nell'infrastruttura critica.

principal.hostname = $host
$host = /.*HoSt.*/ nocase
re.regex(network.email.from, `.*altostrat\.com`) nocase

match:
  $host over 10m

Esempio: espressione regolare del nome host

Regola

L'esempio seguente identifica qualsiasi attività di log in cui l'entità hostname è identificata come server web (webserver) o di sviluppo (devserver). Utilizza un'espressione regolare senza distinzione tra maiuscole e minuscole per assicurarsi che le variazioni nelle convenzioni di denominazione non comportino rilevamenti mancanti.

rule WebServerOrDevServerActivity {
meta:
 author = "Alex"
 description = "Detects events where the principal hostname is 'webserver' or 'devserver', ignoring case."
 severity = "Informational"

events:
 $e.principal.hostname = /webserver|devserver/ nocase

condition:
 $e
}

Cerca

Nell'esempio seguente, principal.hostname = /webserver|devserver/ nocase corrisponde a nomi host come "WebServer01", "devserver-test", "MyWebServers". Questo è un caso d'uso comune per trovare un evento specifico.

// Use /regex/ followed by nocase for a case-insensitive match
principal.hostname = /webserver|devserver/ nocase

Dashboard

Sebbene questo esempio specifico non sia visualizzato in una dashboard, questa regola fornisce avvisi attivi e rilevamento persistente. A differenza di una dashboard, che richiede una revisione manuale, questo garantisce che ogni istanza di attività su questi server venga automaticamente segnalata e registrata nel motore di rilevamento per una ricerca immediata.

Regola

Mentre utilizzi la ricerca manuale per le indagini in un determinato momento, le regole di rilevamento forniscono un monitoraggio continuo dei dati di telemetria 24 ore su 24, 7 giorni su 7. Puoi convertire una query di ricerca riuscita in una regola YARA-L per automatizzare il processo di generazione degli avvisi.

Vantaggi principali delle regole:

  • Avvisi in tempo reale: segnala automaticamente le corrispondenze non appena entrano nel sistema.
  • Persistenza: non è più necessario inserire manualmente i termini di ricerca.
  • Azioni di risultato: vengono inserite direttamente nella visualizzazione di rilevamento per il triage degli analisti e la risposta agli incidenti.

Cerca

Gli analisti della sicurezza utilizzano spesso regex per eseguire ricerche nei log non analizzati e non elaborati all'interno di Google SecOps. Questa azione consente una corrispondenza flessibile dei pattern per trovare artefatti specifici, anche se non sono completamente strutturati o indicizzati. La sintassi utilizza le barre:

raw = /host/

Questa query restituisce qualsiasi riga di log non elaborato in cui viene visualizzata la sequenza di caratteri "host". Alcuni esempi di contenuti dei log non elaborati corrispondenti potrebbero includere "hostname": "myhost123".

Dashboard

Non esiste una variante della dashboard dedicata per questo tipo di evento specifico. Per visualizzare questi rilevamenti su larga scala, puoi:

  • Mappa metadata.event_type a un grafico a barre o a torta in Dashboard Builder.
  • Monitora la frequenza di questi eventi in finestre di 7, 30 o 90 giorni per identificare anomalie nel comportamento degli utenti.

Campi ripetuti con condizioni universali

Caso d'uso: controlla gli eventi che contengono elenchi di dati (campi ripetuti) per assicurarti che non siano presenti eccezioni attendibili. Ad esempio, verifica che ogni indirizzo IP associato a un accesso non rientri in un intervallo sicuro noto.

Logica chiave: utilizza l'operatore all per valutare ogni elemento in un campo ripetuto rispetto a una condizione specifica e mostra come l'assegnazione di un campo ripetuto a una variabile segnaposto (ad esempio, $ip) crea un rilevamento distinto per ogni valore univoco nell'elenco.

Esempio: convalida dell'IP di accesso sospetto

Regola

La seguente regola cerca eventi di accesso in cui tutti gli indirizzi IP di origine non corrispondono a un indirizzo IP noto per essere sicuro in un intervallo di tempo di cinque minuti (5m).

rule SuspiciousIPLogins {
meta:
  author = "alice@example.com"

events:
  $e.metadata.event_type = "USER_LOGIN"

  // Detects if all source IP addresses in an event do not match "100.97.16.0"
  // For example, if an event has source IP addresses
  // ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
  // it will be detected since "100.97.16.1", "100.97.16.2",
  // and "100.97.16.3" all do not match "100.97.16.0".

  all $e.principal.ip != "100.97.16.0"

  // Assigns placeholder variable $ip to the $e.principal.ip repeated field.
  // There will be one detection per source IP address.
  // For example, if an event has source IP addresses
  // ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
  // there will be one detection per address.

  $e.principal.ip = $ip

match:
  $ip over 5m

condition:
  $e
}

Cerca

metadata.event_type = "USER_LOGIN"

// Detects if all source IP addresses in an event do not match "100.97.16.0"
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// it will be detected since "100.97.16.1", "100.97.16.2",
// and "100.97.16.3" all do not match "100.97.16.0".

all principal.ip != "100.97.16.0"

// Assigns placeholder variable $ip to the $e.principal.ip repeated field.
// There will be one detection per source IP address.
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// there will be one detection per address.

principal.ip = $ip

match:
  $ip over 5m

Dashboard

metadata.event_type = "USER_LOGIN"

// Detects if all source IP addresses in an event do not match "100.97.16.0"
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// it will be detected since "100.97.16.1", "100.97.16.2",
// and "100.97.16.3" all do not match "100.97.16.0".

all principal.ip != "100.97.16.0"

// Assigns placeholder variable $ip to the $e.principal.ip repeated field.
// There will be one detection per source IP address.
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// there will be one detection per address.

principal.ip = $ip

match:
  $ip over 5m

Windowing avanzato

Questa sezione copre pattern e rilevamenti multifase attivati dall'attività di altre regole.

Argomento Esempi
Correlazione di più eventi Rilevamento dell'accesso da più città; Creazione ed eliminazione rapida di utenti
Finestra temporale scorrevole nelle query Rilevamento di eventi sequenziali mancanti
Query multi-evento Rilevamento di accessi ad alta frequenza
Query su più eventi con risultati calcolati Attacco di forza bruta seguito da accesso riuscito; Corrispondenza host con finestra temporale

Correlazione multievento

Questa sezione mostra esempi su come monitorare entità (utenti o host) in più eventi o intervalli di tempo per identificare pattern comportamentali.

Caso d'uso: rileva un viaggio impossibile in cui un singolo utente si connette da due o più città in meno di cinque (5m) minuti.

Logica chiave: utilizza la sezione match per raggruppare per $user e #city > 1 per trovare valori di località distinti.

Esempio: rilevamento dell'accesso da più città

Regola

La seguente regola cerca gli utenti che hanno eseguito l'accesso alla tua azienda da due o più città in meno di 5 (5m) minuti, dove $user è la variabile match, $udm è la variabile evento e $city e $user sono le variabili segnaposto:

rule DifferentCityLogin {
meta:

events:
  $udm.metadata.event_type = "USER_LOGIN"
  $udm.principal.user.userid = $user
  $udm.principal.location.city = $city

match:
  $user over 5m

condition:
  $udm and #city > 1
}

La seguente spiegazione descrive il funzionamento di questa regola:

  • Raggruppa gli eventi con il nome utente ($user) e lo restituisce ($user) quando viene trovata una corrispondenza.
  • Il periodo di tempo è di cinque minuti (5m); vengono correlati solo gli eventi che si verificano a meno di 5 minuti (5m) di distanza l'uno dall'altro.
  • Cerca un gruppo di eventi ($udm) il cui tipo di evento è USER_LOGIN.
  • Per questo gruppo di eventi, la regola chiama l'ID utente $user e la città di accesso $city.
  • Restituisce una corrispondenza se il numero distinto di valori city (indicati da #city) è maggiore di 1 nel gruppo di eventi ($udm) nell'intervallo di tempo di 5 minuti (5m).

Cerca

La seguente query di esempio esegue una ricerca statistica equivalente per identificare i pattern di spostamento impossibile. Raggruppa gli eventi USER_LOGIN per utente in un intervallo di cinque minuti (5m) e filtra i risultati in modo da mostrare solo le istanze in cui vengono rilevate più città distinte per una singola identità.

events:
  metadata.event_type = "USER_LOGIN"
  principal.user.userid = $user
  principal.location.city = $city

match:
  $user over 5m

condition:
  #city > 1

Dashboard

La seguente query di esempio fornisce una visualizzazione della dashboard equivalente per monitorare la potenziale compromissione dell'account. Aggrega gli eventi USER_LOGIN per utente in un intervallo di cinque minuti (5m) e filtra le istanze in cui una singola identità è associata a più città distinte (#city), consentendoti di tracciare queste anomalie geografiche ad alto rischio nel tempo.

events:
  metadata.event_type = "USER_LOGIN"
  principal.user.userid = $user
  principal.location.city = $city

match:
  $user over 5m

condition:
  #city > 1

Creazione ed eliminazione rapida degli utenti

Caso d'uso: identifica gli account usa e getta creati ed eliminati entro un periodo di 4 ore.

Logica chiave: unisci due tipi di eventi (USER_CREATION e USER_DELETION) in una variabile $user condivisa e confronta i relativi timestamp.

Esempio: creazione ed eliminazione rapida di utenti

Regola

Il seguente esempio di regola cerca gli utenti che sono stati creati e poi eliminati entro 4 ore (4h), dove $create e $delete sono le variabili evento, $user è la variabile match e non sono presenti variabili segnaposto:

rule UserCreationThenDeletion {
meta:

events:
  $create.target.user.userid = $user
  $create.metadata.event_type = "USER_CREATION"

  $delete.target.user.userid = $user
  $delete.metadata.event_type = "USER_DELETION"

  $create.metadata.event_timestamp.seconds <=
     $delete.metadata.event_timestamp.seconds

match:
  $user over 4h

condition:
  $create and $delete
}

Cerca

L'esempio seguente mostra una ricerca di statistiche multi-evento utilizzata per identificare rapidi cambiamenti del ciclo di vita dell'account. Questa query restituisce una riga per utente in un intervallo di quattro ore, mettendo in correlazione la creazione e l'eliminazione delle identità.

Poiché la ricerca restituisce per impostazione predefinita qualsiasi finestra contenente gli eventi specificati, non è necessaria una sezione condition.

$create.target.user.userid = $user
$create.metadata.event_type = "USER_CREATION"

$delete.target.user.userid = $user
$delete.metadata.event_type = "USER_DELETION"

$create.metadata.event_timestamp.seconds <=
$delete.metadata.event_timestamp.seconds

match:
  $user over 4h

Dashboard

L'esempio seguente mostra una ricerca nella dashboard con più eventi progettata per tracciare le tendenze del ciclo di vita dell'account nel tempo. Utilizzando una finestra mobile (by 4h), i risultati vengono mappati in bucket di tempo discreti e non sovrapposti, il che è ideale per la visualizzazione.

Questa variante include una sezione outcome per calcolare il conteggio distinto degli eventi di creazione all'interno di ogni finestra. A differenza della ricerca precedente, questa versione non richiede la restituzione di variabili evento specifiche, perché l'attenzione è rivolta ai valori statistici aggregati anziché alle singole righe di log.

$create.target.user.userid = $user
$create.metadata.event_type = "USER_CREATION"

$delete.target.user.userid = $user
$delete.metadata.event_type = "USER_DELETION"

$create.metadata.event_timestamp.seconds <=
$delete.metadata.event_timestamp.seconds

match:
  $user by 4h

outcome:
  $event_count = count_distinct($create.metadata.id)

Finestra mobile nelle query

Caso d'uso: per rilevare un potenziale problema di sicurezza in cui un evento iniziale (da firewall_1) non è seguito da un evento successivo previsto (da firewall_2) sullo stesso host entro un periodo di tempo specifico.

Logica chiave:

  • Evento pivot: la regola si concentra sugli eventi di firewall_1, designati come $e1. Ogni volta che si verifica un evento $e1, questo funge da pivot.
  • Finestra temporale: la sezione match ($host over 10m after $e1) definisce una finestra di 10 minuti che inizia immediatamente dopo ogni evento $e1. Questa finestra scorre con ogni nuovo evento $e1.
  • Correlazione: gli eventi vengono raggruppati per nome host ($host).
  • Condizione per il rilevamento ($e1 e $e2): viene attivato un rilevamento per un determinato host se:
    • È presente un evento di firewall_1 ($e1).
    • AND, entro 10 minuti da quell'evento $e1 specifico, viene trovato l'evento NO di firewall_2 ($e2) per lo stesso host.

Esempio: rilevamento di eventi sequenziali mancanti

Regola

L'esempio seguente identifica le istanze in cui un evento secondario non si verifica dopo un attivatore principale. Utilizzando la condizione !$e2 entro un intervallo di 10 minuti, questa regola segnala la telemetria mancante, in particolare quando un log del firewall viene visualizzato in una posizione, ma non appare nell'hop successivo previsto, il che indica un potenziale divario di visibilità o un calo del traffico.

rule MissingSequentialEvent {
meta:
  author = "alice@example.com"

events:
  $e1.metadata.product_name = "firewall_1"
  $e1.principal.hostname = $host

  $e2.metadata.product_name = "firewall_2"
  $e2.principal.hostname = $host

match:
// $e1 is the pivot; the 10-minute window starts at the $e1 timestamp
  $host over 10m after $e1

condition:
  $e1 and !$e2
}

Cerca

L'esempio seguente mostra una ricerca sequenziale utilizzata per identificare le lacune nella telemetria tra due origini. Utilizzando $e1 come pivot, la ricerca cerca un evento firewall principale che non sia seguito da un evento corrispondente su un secondo firewall entro 10 minuti. Si tratta di un modo molto efficace per cercare manualmente "buchi neri" nel traffico di rete o errori di logging durante un'indagine.

$e1.metadata.product_name = "firewall_1"
$e1.principal.hostname = $host

$e2.metadata.product_name = "firewall_2"
$e2.principal.hostname = $host

match:
// $e1 is the pivot; the 10-minute window starts at the $e1 timestamp
  $host over 10m after $e1

condition:
  $e1 and !$e2

Dashboard

L'esempio seguente fornisce un'analisi del gap di visibilità progettata per una visualizzazione della dashboard. Aggregando le istanze in cui un evento secondario non segue un evento principale, puoi visualizzare l'affidabilità della pipeline di logging nel tempo. Tracciare questi eventi "mancanti" aiuta a identificare zone morte persistenti nella visibilità della rete o problemi di configurazione in nomi host specifici.

$e1.metadata.product_name = "firewall_1"
$e1.principal.hostname = $host

$e2.metadata.product_name = "firewall_2"
$e2.principal.hostname = $host

match:
// $e1 is the pivot; the 10-minute window starts at the $e1 timestamp
  $host over 10m after $e1

condition:
  $e1 and !$e2

Query su più eventi

  • Caso d'uso: identifica attività ad alta frequenza o brute force monitorando una singola entità (ad esempio un utente o un host) in più occorrenze di un evento entro un periodo di tempo specifico.

  • Logica chiave: utilizza una sezione match per raggruppare gli eventi in base a una variabile specifica e una sezione condition per verificare un conteggio di soglia (ad esempio #e >= 10) nell'intervallo di tempo definito.

Una tipica regola multi-evento include:

  • Variabili evento per distinguere tra gli eventi.
  • Una sezione match che specifica l'intervallo di tempo in cui gli eventi devono essere raggruppati.
  • Una sezione condition che specifica la condizione che deve attivare il rilevamento e verifica l'esistenza di più eventi.

Nella Ricerca, le query multievento sono definite da più di un evento in una query. Per le regole, esistono due modi per definirlo:

  • Più eventi: (ad esempio, event1 = successful login, event2 = failed login).

  • Attivatori basati su condizioni: la condizione viene indicata per attivarsi solo quando più eventi soddisfano i criteri (ad esempio event1 > 10). Questo tipo di regola deve includere anche una sezione outcome.

Esempio: rilevamento degli accessi ad alta frequenza

Regola

La seguente regola cerca un utente che ha eseguito l'accesso almeno 10 volte in meno di 10 minuti:

rule MultiEventRule {
meta:
  author = "noone@altostrat.com"

events:
  $e.metadata.event_type = "USER_LOGIN"
  $e.principal.user.userid = $user

match:
  $user over 10m

condition:
  #e >= 10
}

Cerca

L'esempio seguente utilizza una ricerca di statistiche multi-evento per identificare l'attività di accesso ad alta frequenza. Segnala qualsiasi istanza in cui un singolo utente genera 10 o più eventi di accesso in un periodo di 10 minuti (10m).

$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user

match:
  $user by 10m

condition:
  #e >= 10

Dashboard

L'esempio seguente utilizza una ricerca multi-evento per monitorare potenziali compromissioni dell'account. Correlano i tentativi di accesso in una finestra temporale mobile di 10 minuti, identificando i casi in cui un utente e un host specifici registrano più tentativi di accesso non riusciti seguiti da uno riuscito, consentendoti di visualizzare in tempo reale i pattern di autenticazione ad alto rischio.

$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user

match:
  $user by 10m

condition:
  #e >= 10

Query multi-evento con risultati calcolati

  • Caso d'uso: applica la logica condizionale per impostare un risk_score in base alla gravità dell'asset o al volume della rete.

  • Logica chiave: utilizza la sezione outcome per calcolare le variabili e la sezione delle condizioni per filtrare in base a queste variabili.

Esempio: attacco di tipo Brute Force seguito da accesso riuscito

L'esempio seguente utilizza la sezione outcome per conteggiare gli eventi all'interno di una finestra match. Questa query genera lo stesso output della query multievento standard, ma mostra come incorporare le variabili calcolate nella logica di rilevamento.

Regola

rule PossibleBruteForceThenSuccessfulLogin {
meta:
  author = "Alex"
  description = "Detects multiple failed login attempts followed by a successful login for the same user and host within a 10-minute window."
  severity = "High"
  tactic = "Credential Access"

events:
  // Define the first type of event: Failed Login
  // We use $failed to represent any event matching these criteria.
  $failed.metadata.event_type = "USER_LOGIN"
  $failed.security_result.action = "FAIL"
  // Extract common fields to correlate on
  $failed.target.user.userid = $user
  $failed.principal.hostname = $hostname

  // Define the second type of event: Successful Login
  // We use $success to represent any event matching these criteria.
  $success.metadata.event_type = "USER_LOGIN"
  $success.security_result.action = "ALLOW"
  // Correlate using the same user and hostname placeholders
  $success.target.user.userid = $user
  $success.principal.hostname = $hostname

match:
  // This section is key for multi-event rules. It groups events:
  // - By the common placeholder variables: $user and $hostname.
  // - Within a time window: by 10m.
  // The rule will evaluate all events matching $failed or $success that share the same $user and $hostname within any given 10-minute period.
  $user, $hostname by 10m

outcome:
  // Calculate aggregate values from the events within the match window.
  $failed_login_count = count($failed.metadata.id)
  $successful_login_count = count($success.metadata.id)

condition:
  // The conditions that must be met *within each matched group* ($user, $hostname over 10m).
  // - #failed >= 5: There must be 5 or more events matching the $failed criteria.
  // - #success >= 1: There must be at least 1 event matching the $success criteria.
  #failed >= 5 and #success >= 1
}

Cerca

// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname

// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname

match:
  // This section is key for multi-event rules. It groups events:
  // - By the common placeholder variables: $user and $hostname.
  // - Within a sliding time window: over 10m.
  // The rule will evaluate all events matching $failed or $success that share
  // the same $user and $hostname within any given 10-minute period.
  $user, $hostname over 10m

Dashboard

// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname

// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname

match:
  // This section is key for multi-event rules. It groups events:
  // - By the common placeholder variables: $user and $hostname.
  // - Within a sliding time window: over 10m.
  // The rule will evaluate all events matching $failed or $success that share
  // the same $user and $hostname within any given 10-minute period.
  $user, $hostname over 10m

Esempio: corrispondenza dell'host con finestra temporale

Regola

La seguente regola esamina due eventi per ottenere il valore di $hostname. Se il valore di $hostname corrisponde a un periodo di 5 minuti (5m), viene applicato un punteggio di gravità. Quando includi un periodo di tempo nella sezione match, la regola esegue il controllo all'interno del periodo di tempo specificato.

rule OutcomeRuleMultiEvent {
meta:
  author = "Google Cloud Security"
events:
  $u.udm.principal.hostname = $hostname
  $asset_context.graph.entity.hostname = $hostname

  $severity = $asset_context.graph.entity.asset.vulnerabilities.severity

match:
  $hostname over 5m

outcome:
  $risk_score =
    max(
        100
      + if($hostname = "my-hostname", 100, 50)
      + if($severity = "HIGH", 10)
      + if($severity = "MEDIUM", 5)
      + if($severity = "LOW", 1)
    )

  $asset_id_list =
    array(
      if($u.principal.asset_id = "",
          "Empty asset id",
          $u.principal.asset_id
      )
    )

  $asset_id_distinct_list = array_distinct($u.principal.asset_id)

  $asset_id_count = count($u.principal.asset_id)

  $asset_id_distinct_count = count_distinct($u.principal.asset_id)

condition:
  $u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}

Cerca

 // Define the first type of event: Failed Login
 // We use $failed to represent any event matching these criteria.
 $failed.metadata.event_type = "USER_LOGIN"
 $failed.security_result.action = "FAIL"
 // Extract common fields to correlate on
 $failed.target.user.userid = $user
 $failed.principal.hostname = $hostname

 // Define the second type of event: Successful Login
 // We use $success to represent any event matching these criteria.
 $success.metadata.event_type = "USER_LOGIN"
 $success.security_result.action = "ALLOW"
 // Correlate using the same user and hostname placeholders
 $success.target.user.userid = $user
 $success.principal.hostname = $hostname

match:
 // This section is key for multi-event rules. It groups events:
 // - By the common placeholder variables: $user and $hostname.
 // - Within a sliding time window: over 10m.
 // The rule will evaluate all events matching $failed or $success that share
 // the same $user and $hostname within any given 10-minute period.
 $user, $hostname over 10m

outcome:
 // Calculate aggregate values from the events within the match window.
 $failed_login_count = count($failed.metadata.id)
 $successful_login_count = count($success.metadata.id)
 ```

Dashboard

// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname

// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname

match:
 // This section is key for multi-event rules. It groups events:
 // - By the common placeholder variables: $user and $hostname.
 // - Within a sliding time window: over 10m.
 // The rule will evaluate all events matching $failed or $success that share
 // the same $user and $hostname within any given 10-minute period.
 $user, $hostname over 10m

outcome:
  // Calculate aggregate values from the events within the match window.
  $failed_login_count = count($failed.metadata.id)
  $successful_login_count = count($success.metadata.id)

Analisi sensibili al contesto

Puoi utilizzare le regole YARA-L per valutare i dati degli eventi UDM rispetto ai dati di contesto dell'indicatore di compromissione (IOC). Questi dati di contesto vengono archiviati come contesti delle entità in Google SecOps.

Gli esempi in questa sezione mostrano come creare analisi sensibili al contesto unendo i campi evento ai feed IOC, come Google Navigazione sicura e i feed personalizzati.

Argomento Esempi
Corrispondenza di hash dei file con gli indicatori di compromissione Avvio di un processo sospetto; Elenchi di minacce di Navigazione sicura
Corrispondenza degli indirizzi IP con gli indicatori di compromissione Rilevamento dei nodi di uscita Tor; Tentativi di accesso multipli non riusciti dalla rete Tor
Corrispondenza dei domini con gli indicatori di compromissione Domini a bassa prevalenza
Corrispondenza degli URL con gli indicatori di compromissione Corrispondenza di URL dannoso dal feed delle minacce
Corrispondenza simultanea di più feed Rilevamento del nodo di uscita Tor e dello strumento di accesso remoto

Corrispondenza degli hash dei file con gli indicatori di compromissione

Caso d'uso: rileva l'esecuzione o la presenza di file identificati come indicatori di compromissione (IOC) nei feed sulle minacce.

Logica chiave: unisci gli eventi di processo o file UDM con le entità file (hash) dei feed IOC nell'Entity Graph.

Esempio: avvio di un processo sospetto

Regola

La seguente regola valuta i dati di processo UDM rispetto ai dati di contesto IOC generici. Cerca un evento di avvio del processo e unisce l'hash del file dell'evento con un hash del file trovato in un grafico delle entità IOC.

rule ProcessLaunch {
  meta:
  events:
    $ioc.graph.metadata.vendor_name = "ACME"
    $ioc.graph.metadata.product_name = "IOCs"
    $ioc.graph.metadata.entity_type = "FILE"
    $ioc.graph.entity.file.sha256 = $hash

    $process.metadata.event_type = "PROCESS_LAUNCH"
    $process.principal.hostname = $hostname
    (
        not $process.target.process.file.sha256 = "" and
        $process.target.process.file.sha256 = $hash
    )

  match:
    $hash over 15m

  condition:
    $ioc and $process
}

Esempio: elenchi di minacce di Navigazione sicura

Regola

Google SecOps acquisisce i dati dagli elenchi delle minacce relativi agli hash dei file, che vengono archiviati come entità. La seguente regola rileva l'esecuzione di un file considerato dannoso da Google Navigazione sicura.

rule safe_browsing_file_execution {
    meta:
        author = "Google Security Operations"
        description = "Example usage of Safe Browsing data, to detect execution of a file that's been deemed malicious"
        severity = "LOW"

    events:
        // find a process launch event, match on hostname
        $execution.metadata.event_type = "PROCESS_LAUNCH"
        $execution.principal.hostname = $hostname

        // join execution event with Safe Browsing graph
        $sb.graph.entity.file.sha256 = $execution.target.process.file.sha256

        // look for files deemed malicious
        $sb.graph.metadata.entity_type = "FILE"
        $sb.graph.metadata.threat_intel.severity = "SEVERITY_HIGH"
        $sb.graph.metadata.product_name = "Google Safe Browsing"
        $sb.graph.metadata.source_type = "GLOBAL_CONTEXT"

    match:
        $hostname over 1h

    outcome:
        $risk_score = max(if($sb.graph.metadata.threat_intel.severity = "SEVERITY_HIGH", 90, 0))

    condition:
        $execution and $sb
}

Corrispondenza degli indirizzi IP con gli indicatori di compromissione

Caso d'uso: rileva la comunicazione di rete con indirizzi IP dannosi noti archiviati nei feed delle minacce.

Logica chiave: unisci gli eventi di rete UDM alle entità indirizzo IP dei feed IOC nel grafico delle entità.

Esempio: rilevamento dei nodi di uscita Tor

Regola

Identifica il traffico di rete proveniente da o che si connette a nodi di uscita Tor noti. Questo esempio unisce gli eventi UDM al feed dei nodi di uscita Tor del feed GCTI, disponibile per tutti i clienti.

rule TorExitNodeMatch {
  meta:
    author = "Google Security Operations"
    description = "Detects traffic from known Tor exit nodes."
    severity = "MEDIUM"

  events:
    // Event based on IP
    $principal_ip = $e.principal.ip

    // Filter Entity Graph to extract feed specific details
    $gcti.graph.metadata.entity_type = "IP_ADDRESS"
    $gcti.graph.metadata.feed = "Tor Exit Nodes"
    $gcti.graph.metadata.product_name = "GCTI Feed"

    // Join the IP data
    $principal_ip = $gcti.graph.entity.ip

  match:
    $principal_ip over 30m

  outcome:
    $threat_feed = array_distinct($gcti.graph.metadata.feed)

  condition:
    $e and $gcti
}

Esempio: più accessi non riusciti dalla rete Tor

Regola

Rilevare più tentativi di accesso non riusciti da una rete Tor. Questo esempio correla gli eventi login_failure con il feed Nodi di uscita Tor e applica una soglia di frequenza utilizzando la sintassi di conteggio (#).

rule TorMultiLoginFailure {
  meta:
    author = "Google Security Operations"
    description = "Detects multiple failed logins from a Tor network."
    severity = "HIGH"

  events:
    $failed_login_event.metadata.product_name = "login"
    $failed_login_event.metadata.product_event_type = "login_failure"
    $failed_login_event.metadata.vendor_name = "Google Workspace"
    $sus_ip = $failed_login_event.principal.ip
    $sus_target_account = $failed_login_event.target.user.email_addresses
    $sus_target_account != ""

    $gcti.graph.metadata.entity_type = "IP_ADDRESS"
    $gcti.graph.metadata.feed = "Tor Exit Nodes"
    $gcti.graph.metadata.product_name = "GCTI Feed"

    // Join the IP data
    $sus_ip = $gcti.graph.entity.ip

  match:
    $sus_ip over 1h

  outcome:
    $event_count = count_distinct($failed_login_event.metadata.id)

  condition:
    $failed_login_event and #failed_login_event >= 10 and $gcti
}

Corrispondenza dei domini con gli indicatori di compromissione

Caso d'uso: rileva l'attività di rete verso domini contrassegnati come indicatori di compromissione (IOC) o domini con bassa prevalenza.

Logica chiave: unisci gli eventi di rete UDM con le entità di dominio dai feed IOC o dai dati di prevalenza nell'Entity Graph utilizzando il nome di dominio o il nome host.

Esempio: domini a bassa prevalenza

Regola

La seguente regola genera un avviso di rilevamento confrontando un dominio a bassa prevalenza con un IOC noto. Unisce un evento di query DNS a dati di prevalenza e a un'entità IOC del feed ET_PRO_IOC.

rule network_prevalence_uncommon_domain_ioc_match {

  meta:
    author = "Google Security Operations"
    description = "Lookup Network DNS queries against Entity Graph for low prevalence domains with a matching IOC entry."
    severity = "MEDIUM"

  events:
    $e.metadata.event_type = "NETWORK_DNS"
    $e.network.dns.questions.name = $hostname

    //only match FQDNs, such as: exclude chrome dns access tests and other internal hosts
    $e.network.dns.questions.name = /(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]/

    //prevalence entity graph lookup
    $p.graph.metadata.entity_type = "DOMAIN_NAME"
    $p.graph.entity.domain.prevalence.rolling_max > 0
    $p.graph.entity.domain.prevalence.rolling_max <= 3
    $p.graph.entity.domain.name = $hostname

    //ioc entity graph lookup
    $i.graph.metadata.vendor_name = "ET_PRO_IOC"
    $i.graph.metadata.entity_type = "DOMAIN_NAME"
    $i.graph.entity.hostname = $hostname

  match:
    $hostname over 10m

  outcome:
    $risk_score = max(
        //increment risk score based upon rolling_max prevalence
        if ( $p.graph.entity.domain.prevalence.rolling_max = 3, 50) +
        if ( $p.graph.entity.domain.prevalence.rolling_max = 2, 70) +
        if ( $p.graph.entity.domain.prevalence.rolling_max = 1, 90)
    )

  condition:
    $e and $p and $i
}

Corrispondenza degli URL con gli indicatori di compromissione

Caso d'uso: rileva l'attività di rete che coinvolge URL dannosi archiviati nei feed delle minacce.

Logica chiave: unisci gli eventi di rete UDM contenenti dati URL alle entità URL dei feed IOC in Entity Graph.

Esempio: corrispondenza di URL dannoso dal feed delle minacce

Regola

La seguente regola rileva gli eventi di rete in cui l'URL richiesto corrisponde a un URL dannoso noto proveniente da un feed di threat intelligence. Mette in correlazione l'evento target.url con le entità URL nel grafico delle entità.

rule ioc_url_threat_feed_match {
  meta:
    author = "Google Security Operations"
    description = "Matches network events against known malicious URLs from threat intelligence feeds."
    severity = "HIGH"

  events:
    // Filter for network traffic containing URL information
    $network_event.metadata.event_type = "NETWORK_HTTP" or $network_event.metadata.event_type = "NETWORK_CONNECTION"
    $url = $network_event.target.url

    // Entity Graph Join: URL Indicators
    $ioc.graph.metadata.entity_type = "URL"
    $ioc.graph.metadata.product_name = "GCTI Feed"
    $ioc.graph.metadata.feed = "Malicious URLs"
    $ioc.graph.entity.url = $url

  match:
    $url over 5m

  outcome:
    $risk_score = 85
    $threat_feed = array_distinct($ioc.graph.metadata.feed)
    $principal_ip = array_distinct($network_event.principal.ip)
    $principal_user = array_distinct($network_event.principal.user.userid)

  condition:
    $network_event and $ioc
}

Corrispondenza multifeed simultanea

Caso d'uso: metti in correlazione le minacce avanzate abbinando più attributi (ad esempio indirizzo IP e hash del file) a feed sulle minacce separati all'interno di una singola query evento.

Logica chiave: unisci un singolo evento UDM con più segnaposto Entity Graph, ognuno dei quali filtra per un threat_feed_name specifico (ad esempio,feed di Google Cloud Threat Intelligence).

Esempio: rilevamento del nodo di uscita Tor e dello strumento di accesso remoto

Regola

La seguente regola segnala il traffico di rete che sembra essere associato a Remote Monitoring and Management (RMM) e che ha origine da o si connette a un nodo di uscita Tor. Collega un evento NETWORK_CONNECTION sia a un feed IP (nodi di uscita Tor) sia a un feed hash di file (strumenti di accesso remoto).

rule tor_and_remote_access_tool_match {
  meta:
    author = "Google Security Operations"
    description = "Matches network connections involving both a Tor exit node and Remote Access Tool malware hashes."
    severity = "CRITICAL"

  events:
    // Filter for network connection events, often recorded by EDR agents
    $e.metadata.event_type = "NETWORK_CONNECTION"
    $target_ip = $e.target.ip
    $process_hash = $e.principal.process.file.sha256

    // IP Feed Join: Tor Exit Nodes
    $gcti_ip.graph.metadata.entity_type = "IP_ADDRESS"
    $gcti_ip.graph.metadata.product_name = "GCTI Feed"
    $gcti_ip.graph.metadata.feed = "Tor Exit Nodes"
    $gcti_ip.graph.entity.ip = $target_ip

    // Hash Feed Join: Remote Access Tools
    $gcti_hash.graph.metadata.entity_type = "FILE"
    $gcti_hash.graph.metadata.product_name = "GCTI Feed"
    $gcti_hash.graph.metadata.feed = "Remote Access Tools"
    $gcti_hash.graph.entity.file.sha256 = $process_hash

  match:
    $target_ip over 10m

  outcome:
    $risk_score = 95
    $ip_feed = array_distinct($gcti_ip.graph.metadata.feed)
    $hash_feed = array_distinct($gcti_hash.graph.metadata.feed)

  condition:
    $e and $gcti_ip and $gcti_hash
}

Rilevamenti compositi

I rilevamenti compositi migliorano il rilevamento delle minacce utilizzando regole composite. Queste regole composite utilizzano come input i rilevamenti di altre regole. In questo modo è possibile rilevare minacce complesse che le singole regole potrebbero non rilevare. Per saperne di più, consulta Panoramica dei rilevamenti compositi.

Argomento Esempi
Filtro ad alto rischio Rilevamento degli utenti amministrativi
Aggregazione e definizione delle soglie Aggregazione dei rischi
Aggregazione delle tattiche Aggregazione delle tattiche MITRE
Rilevamenti compositi sequenziali Tentativo di attacco Brute Force seguito da accesso riuscito
Rilevamento sensibile al contesto Arricchimento della threat intelligence
Rilevamenti di co-occorrenze Co-occorrenza di escalation dei privilegi ed esfiltrazione

Filtro ad alto rischio

Caso d'uso: filtra le rilevazioni esistenti per attributi ad alto rischio, ad esempio attività che coinvolgono account amministrativi.

Logica chiave: opera su risultati o campi di metadati all'interno dei risultati esistenti.

I rilevamenti compositi di filtraggio ad alto rischio sono la forma più semplice di rilevamento composito che opera sui campi all'interno dei risultati del rilevamento, come le variabili di risultato o i metadati delle regole. Aiutano a filtrare i rilevamenti per condizioni che potrebbero indicare un rischio più elevato, come un utente amministratore o un ambiente di produzione.

Esempio: rilevamento di utenti amministrativi

Regola

La seguente regola composta cerca i rilevamenti esistenti in cui l'attore è identificato come utente amministrativo e applica uno scoring del rischio standardizzato.

rule composite_admin_detection {
meta:
  rule_name = "Detection with Admin User"
  author = "Google Cloud Security"
  description = "Composite rule that looks for any detections where the actor is an admin user"
  severity = "Medium"

events:
  $rule_name = $d.detection.detection.rule_name
  $principal_user = $d.detection.detection.variables["principal_users"]
  $principal_user = /admin|root/ nocase

match:
  $principal_user over 1h
outcome:
  $risk_score = 75
  $upstream_rules = array_distinct($rule_name)

condition:
  $d
}

Cerca

La seguente ricerca statistica identifica e aggrega l'attività per gli account con privilegi elevati. È progettato per trovare tutti i nomi di regole univoci che hanno attivato rilevamenti che coinvolgono utenti "amministratore" o "root".

In questa query specifica, la finestra temporale viene rimossa per eseguire una singola analisi statistica su tutti i rilevamenti nel periodo di tempo selezionato. Inoltre, poiché si tratta di una ricerca non aggregata incentrata sui dati di rilevamento esistenti, le sezioni Eventi, Variabili evento e Condizione non sono obbligatorie.

$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_users"]
$principal_user = /admin|root/ nocase

match:
  $principal_user

outcome:
  $upstream_rules = array_distinct($rule_name)

Dashboard

Questa query della dashboard ti consente di visualizzare quali regole specifiche rilevano più spesso l'attività correlata all'amministratore. È progettata per fornire una panoramica generale delle tendenze di rilevamento nel tuo ambiente.

Nota la variazione della variabile match e dell'aggregazione outcome rispetto agli esempi precedenti. Questa query raggruppa i risultati per nome della regola e calcola un conteggio degli utenti amministratore rilevati per ciascuna.

$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_users"]
$principal_user = /admin|root/ nocase

match:
  $rule_name

outcome:
  $admin_detections = count($principal_user)

Aggregazione e soglie

Caso d'uso: identifica gli utenti o gli host che generano un volume elevato di avvisi o accumulano punteggi di rischio significativi nel tempo.

Logica chiave: utilizza sum() o count_distinct() per analizzare i dati di rilevamento aggregati.

Le regole di rilevamento composite di aggregazione consentono di raggruppare i risultati del rilevamento in base ad attributi condivisi, come un nome host o un nome utente, e di analizzare i dati aggregati. Ecco alcuni casi d'uso comuni:

  • Identificando gli utenti che generano un volume elevato di avvisi di sicurezza o di rischio aggregato.
  • Rilevamento di host con pattern di attività insoliti mediante l'aggregazione di rilevamenti correlati.

Esempio: aggregazione dei rischi

Regola

Questa regola aggrega lo scoring del rischio di un singolo utente in un periodo di 48 ore. Identifica gli utenti il cui rischio cumulativo in più rilevamenti supera una soglia specifica.

In questa logica aggiornata, detection.detection.outcomes viene sostituito da variabili di campo mappa, che memorizzano sia le variabili match sia le variabili outcome. Inoltre, la variabile di risultato $principal_users viene rimossa perché ogni rilevamento contiene esattamente un valore della variabile di corrispondenza, che è già acquisito.

rule composite_risk_aggregation {
meta:
  rule_name = "Risk Aggregation Composite"
  author = "Google Cloud Security"
  description = "Composite detection that aggregates risk of a user over 48 hours"
  severity = "High"

events:
  $rule_name = $d.detection.detection.rule_name
  $principal_user = $d.detection.detection.outcomes["principal_users"]
  $risk = $d.detection.detection.risk_score

match:
  $principal_user over 48h

outcome:
  $risk_score = 90
  $cumulative_risk = sum($risk)
  $upstream_rules = array_distinct($rule_name)

condition:
  $d and $cumulative_risk > 500
}

Cerca

Questa ricerca statistica aggrega i dati di rilevamento per calcolare il rischio totale di un utente in un periodo di 48 ore. Genera una riga per utente principale per ogni finestra, fornendo una visualizzazione di alto livello del rischio dell'account in più tipi di rilevamento.

In questa variante, le variabili evento non sono obbligatorie. Mentre il motore delle regole filtra automaticamente i rilevamenti senza un utente principale, questa ricerca richiede un filtro esplicito ($principal_user != "") per assicurarsi che i risultati includano solo dati compilati. Per impostazione predefinita, la query restituisce risultati solo quando è presente una o più rilevazioni per un determinato utente.

$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_user"]
$principal_user != ""
$risk = detection.detection.risk_score

match:
  $principal_user over 48h

outcome:
  $risk_score = 90
  $cumulative_risk = sum($risk)
  $upstream_rules = array_distinct($rule_name)

condition:
  $cumulative_risk > 500

Dashboard

Questa variante è progettata specificamente per le dashboard per tracciare il rischio utente e l'attività di rilevamento nel tempo. Aggrega i dati in bucket discreti, il che lo rende ideale per visualizzare tendenze come il volume di regole uniche attivate o il conteggio totale dei rilevamenti per utente.

In questa query, la finestra viene cambiata da una finestra scorrevole (hop) a una finestra a cascata (by 48h). In questo modo, i punti dati vengono mappati a segmenti di tempo non sovrapposti, il che fornisce una visualizzazione più pulita per i grafici delle serie temporali. Come per altre ricerche non aggregate, le variabili degli eventi non sono obbligatorie e la sezione outcome viene espansa per includere conteggi distinti sia per i nomi delle regole sia per gli ID di rilevamento.

$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_user"]
$principal_user != ""
$risk = detection.detection.risk_score

match:
  $principal_user by 48h

outcome:
  $cumulative_risk = sum($risk)
  $rule_count = count_distinct($rule_name)
  $detection_count = count_distinct(detection.id)

condition:
  $cumulative_risk > 500

Aggregazione delle tattiche

Caso d'uso: identifica gli utenti la cui attività ha attivato rilevamenti in più tattiche MITRE ATT&CK distinte, suggerendo un ciclo di vita dell'attacco in corso (ad esempio, il passaggio da Accesso iniziale a Esfiltrazione).

Logica chiave: utilizza count_distinct($tactic) per attivarsi solo quando un utente supera una soglia specifica di tattiche diverse in un periodo di 48 ore.

Esempio: aggregazione delle tattiche MITRE

Regola

rule composite_tactic_aggregation {
meta:
  rule_name = "MITRE Tactic Aggregation Composite"
  author = "Google Cloud Security"
  description = "Composite detection that detects if a user has triggered detections over multiple mitre tactics."
  severity = "Medium"

events:
  $principal_user = $d.detection.detection.outcomes["principal_users"]
  $tactic = $d.detection.detection.outcomes["mitre_tactic"]
  $rule_name = $d.detection.detection.rule_name

match:
  $principal_user over 48h

outcome:
  $mitre_tactics_count = count_distinct($tactic)
  $mitre_tactics = array_distinct($tactic)
  $calculated_risk = 50 + (15 * $mitre_tactics_count)
  $upstream_rules = array_distinct($rule_name)

condition:
  $d and $mitre_tactics_count > 1 }

Cerca

L'esempio seguente mostra una variante di ricerca progettata per gli sviluppatori di sicurezza che devono correlare i rilevamenti esistenti e applicare la ponderazione dinamica del rischio. Questa logica di query estrae le tattiche MITRE ATT&CK e le informazioni utente dall'origine dati detection, raggruppa l'attività in base all'utente principale e calcola uno scoring del rischio personalizzato in base alla diversità delle tattiche osservate.

detection.detection.outcomes.key = "principal_users"
detection.detection.outcomes.key = "mitre_tactic"
$principal_user = detection.detection.outcomes["principal_users"]
$tactic = detection.detection.outcomes["mitre_tactic"]
$rule_name = detection.detection.rule_name

match:
  $principal_user

outcome:
  $mitre_tactics_count = count_distinct($tactic)
  $mitre_tactics = array_distinct($tactic)
  $upstream_rules = array_distinct($rule_name)
  $calculated_risk = 50 + (15 * $mitre_tactics_count)
  $risk_score = if($calculated_risk > 100, 100,   $calculated_risk)

Dashboard

L'esempio seguente illustra una variante di Dashboard della stessa logica di analisi del rilevamento. Se utilizzata all'interno delle dashboard di Google SecOps, questa query consente agli sviluppatori di visualizzare gli utenti ad alto rischio mettendo in correlazione i risultati del rilevamento in diverse regole. La logica estrae l'entità principale e le tattiche MITRE, aggrega i risultati e applica uno scoring del rischio limitato per dare la priorità alle attività di indagine direttamente all'interno di un widget della dashboard.

detection.detection.outcomes.key = "principal_users"
detection.detection.outcomes.key = "mitre_tactic"
$principal_user = detection.detection.outcomes["principal_users"]
$tactic = detection.detection.outcomes["mitre_tactic"]
$rule_name = detection.detection.rule_name

match:
  $principal_user

outcome:
  $mitre_tactics_count = count_distinct($tactic)
  $mitre_tactics = array_distinct($tactic)
  $upstream_rules = array_distinct($rule_name)
  $calculated_risk = 50 + (15 * $mitre_tactics_count)
  $risk_score = if($calculated_risk > 100, 100,   $calculated_risk)
  ```

Rilevamenti compositi sequenziali

Caso d'uso: identifica i pattern di attacco critici in cui l'ordine delle operazioni è essenziale, ad esempio il rilevamento di un accesso all'account riuscito che si verifica solo dopo una serie di avvisi di tentativi di attacco di tipo brute force dallo stesso indirizzo IP.

Logica chiave: mette in correlazione un rilevamento precedente con un evento UDM non elaborato successivo unendoli in base a una variabile comune (ad esempio $bruteforce_ip) e utilizzando un confronto dei timestamp per garantire che gli eventi si siano verificati nella sequenza corretta.

I rilevamenti compositi sequenziali identificano pattern di eventi correlati in cui la sequenza di rilevamenti è importante, ad esempio un tentativo di accesso con attacco di tipo brute force, seguito da un accesso riuscito. Questi pattern possono coinvolgere più rilevamenti di base o una combinazione di rilevamenti di base ed eventi.

Esempio: tentativo di attacco brute force seguito da un accesso riuscito

Regola

La seguente regola composita identifica i pattern di eventi correlati in cui la sequenza è importante. In particolare, cerca un rilevamento di attacco brute force di Google Workspace seguito da un evento di accesso riuscito dallo stesso IP di origine entro un periodo di 24 ore.

rule composite_bruteforce_login {
meta:
  rule_name = "Bruteforce Login Composite"
  author = "Google Cloud Security"
  description = "Detects when an IP address associated with a Workspace brute force attempt successfully logs in"
  severity = "High"

events:
  $bruteforce_detection.detection.detection.rule_name = /Workspace Anomalous Failed Logins/
  $bruteforce_ip = $bruteforce_detection.detection.detection.variables["principal_ips"]

  $login_event.metadata.product_name = "login"
  $login_event.metadata.product_event_type = "login_success"
  $login_event.metadata.vendor_name = "Google Workspace"
  $login_ip = $login_event.principal.ip

  // Ensure the brute force detection and successful login occurred from the same IP
  $login_ip = $bruteforce_ip

  $target_account = $login_event.target.user.email_addresses

  // Ensure the brute force detection occurred before the successful login
  $bruteforce_detection.detection.detection_time.seconds < $login_event.metadata.event_timestamp.seconds

match:
  $bruteforce_ip over 24h

outcome:
  $risk_score = 90
  $principal_users = array_distinct($target_account)

condition:
  $bruteforce_detection and $login_event
}

Cerca

$bruteforce_detection.detection.detection.rule_name = /Workspace Anomalous Failed Logins/
$bruteforce_ip = $bruteforce_detection.detection.detection.variables["principal_ips"]

$login_event.metadata.product_name = "login"
$login_event.metadata.product_event_type = "login_success"
$login_event.metadata.vendor_name = "Google Workspace"
$login_ip = $login_event.principal.ip

// Ensure the brute force detection and successful login occurred from the same IP
$login_ip = $bruteforce_ip

$target_account = $login_event.target.user.email_addresses

// Ensure the brute force detection occurred before the successful login
$bruteforce_detection.detection.detection_time.seconds < $login_event.metadata.event_timestamp.seconds

match:
  $bruteforce_ip over 24h

outcome:
  $principal_users = array_distinct($target_account)

condition:
  $bruteforce_detection and $login_event

Dashboard

Le dashboard si concentrano sulla visualizzazione dei dati degli eventi non elaborati, mentre la logica di rilevamento composito correla gli avvisi di rilevamento esistenti con gli eventi successivi. Questa analisi multilivello è ottimizzata per il motore di rilevamento anziché per i widget della dashboard in tempo reale.

Rilevamento sensibile al contesto

Caso d'uso: arricchisci i rilevamenti esistenti con la threat intelligence esterna per verificare se un avviso coinvolge entità dannose note, ad esempio controllando se un indirizzo IP segnalato in un rilevamento di sicurezza è presente anche in un feed globale di minacce dei nodi di uscita TOR.

Logica chiave: utilizza regole composite per unire i risultati del rilevamento con i dati del grafico GLOBAL_CONTEXT (ad esempio,i feed di Google Cloud Threat Intelligence) abbinando un attributo condiviso come un indirizzo IP.

I rilevamenti compositi sensibili al contesto arricchiscono i rilevamenti con un contesto aggiuntivo, ad esempio gli indirizzi IP trovati nei feed delle minacce.

Esempio: arricchimento della threat intelligence

Regola

La seguente regola composita aggiunge automaticamente un contesto aggiuntivo dal feed di intelligence TOR ai rilevamenti esistenti. Mette in correlazione un indirizzo IP trovato in un rilevamento precedente con il feed dei nodi di uscita TOR per aumentare la gravità e il punteggio di rischio del risultato.

rule composite_tor_enrichment {
meta:
  rule_name = "Detection with IP from TOR Feed"
  author = "Google Cloud Security"
  description = "Adds additional context from the TOR intel feed to detections"
  severity = "High"

events:
  $rule_name = $d.detection.detection.rule_name

  $gcti.graph.metadata.entity_type = "IP_ADDRESS"
  $gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence"
  $gcti.graph.metadata.source_type = "GLOBAL_CONTEXT"
  $gcti.graph.metadata.product_name = "GCTI Feed"
  $gcti.graph.metadata.feed = "Tor Exit Nodes"

  $detection_ip = $d.detection.detection.variables["principal_ips"]
  $detection_ip = $gcti.graph.entity.ip

match:
  $detection_ip, $rule_name over 1h

outcome:
  $risk_score = 80

condition:
  $d and $gcti
}

Cerca

$rule_name = $d.detection.detection.rule_name

$gcti.graph.metadata.entity_type = "IP_ADDRESS"
$gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence"
$gcti.graph.metadata.source_type = "GLOBAL_CONTEXT"
$gcti.graph.metadata.product_name = "GCTI Feed"
$gcti.graph.metadata.feed = "Tor Exit Nodes"

$detection_ip = $d.detection.detection.variables["principal_ips"]
$detection_ip = $gcti.graph.entity.ip

match:
  $detection_ip, $rule_name over 1h

condition:
  $d and $gcti

Dashboard

Rilevamenti di co-occorrenza

Caso d'uso: rileva una combinazione di tattiche correlate attivate dalla stessa entità in un periodo di tempo specifico, ad esempio, identifica un utente che ha attivato sia un rilevamento dell'escalation dei privilegi sia un rilevamento dell'esfiltrazione di dati entro 48 ore.

Logica chiave: utilizza una forma di aggregazione per correlare più tipi di rilevamento distinti unendoli in una variabile di entità condivisa (ad esempio $pe_user) all'interno della sezione match.

I rilevamenti compositi di co-occorrenza sono una forma di aggregazione che può rilevare una combinazione di eventi correlati, ad esempio una combinazione di rilevamenti di escalation dei privilegi e di esfiltrazione di dati attivati da un utente.

Esempio: co-occorrenza di escalation dei privilegi ed esfiltrazione

Regola

La seguente regola composita cerca una sequenza o una combinazione specifica di rilevamenti (escalation dei privilegi seguita da esfiltrazione) associata allo stesso utente in un periodo di 48 ore.

rule composite_privesc_exfil_sequential {
meta:
  rule_name = "Privilege Escalation and Exfiltration Composite"
  author = "Google Cloud Security"
  description = "Looks for a detection sequence of privilege escalation followed by exfiltration."
  severity = "High"

events:
  $privilege_escalation.detection.detection.rule_labels["tactic"] = "TA0004"
  $exfiltration.detection.detection.rule_labels["tactic"] = "TA0010"

  $privesc_user = $privilege_escalation.detection.detection.variables["principal_users"]
  $exfil_user = $exfiltration.detection.detection.variables["principal_users"]

  $privesc_user = $exfil_user

  $privilege_escalation.detection.detection_time.seconds < $exfiltration.detection.detection_time.seconds

match:
  $privesc_user over 48h

outcome:
  $risk_score = 75
  $privesc_rules = array_distinct($privilege_escalation.detection.detection.rule_name)
  $exfil_rules = array_distinct($exfiltration.detection.detection.rule_name)

condition:
  $privilege_escalation and $exfiltration
}

Cerca

$privilege_escalation.detection.detection.rule_labels["tactic"] = "TA0004"
$exfiltration.detection.detection.rule_labels["tactic"] = "TA0010"

$privesc_user = $privilege_escalation.detection.detection.variables["principal_users"]
$exfil_user = $exfiltration.detection.detection.variables["principal_users"]

$privesc_user = $exfil_user

$privilege_escalation.detection.detection_time.seconds < $exfiltration.detection.detection_time.seconds

match:
  $privesc_user over 48h

outcome:
  $privesc_rules = array_distinct($privilege_escalation.detection.detection.rule_name)
  $exfil_rules = array_distinct($exfiltration.detection.detection.rule_name)

condition:
  $privilege_escalation and $exfiltration

Dashboard

Gestione di risultati e variabili

Questa sezione mostra esempi di calcolo del rischio e normalizzazione dei dati per il consumo downstream.

Argomento Esempi
Condizionali dei risultati Filtrare in base allo scoring del rischio calcolato
Query su un singolo evento con risultato Tagging della gravità point-in-time
Scoring del rischio basato sulla rete Regola di scoring del rischio basata sulla rete
Rifattorizza la logica multievento (pre-rifattorizzazione) Refactoring del risultato (pre-refactoring)
Refactor multi-event logic (post-refactor) Outcome refactor (post-refactor)
Assegnazione della funzione al segnaposto

Query con la sezione outcome

Puoi aggiungere la sezione facoltativa outcome in una regola YARA-L 2.0 per estrarre informazioni aggiuntive su ogni rilevamento. Nella sezione condition puoi anche specificare condizioni sulle variabili di risultato. Puoi utilizzare la sezione outcome di una regola di rilevamento per impostare le variabili per l'utilizzo downstream. Ad esempio, puoi impostare un punteggio di gravità in base ai dati degli eventi analizzati.

Per ulteriori informazioni, consulta le seguenti risorse:

Condizionali di risultato

Caso d'uso: filtra i rilevamenti in base allo scoring del rischio calcolato per ridurre il rumore e assicurarti che solo gli eventi con un'alta confidenza o gravità attivino gli avvisi. Ciò è utile per eliminare le attività a basso rischio che non soddisfano una soglia aziendale specifica.

Logica chiave: definisce le variabili nella sezioneoutcome utilizzando la matematica condizionale (ad esempio, aggiungendo il rischio in base alle dimensioni del file o all'ora del giorno) e poi fa riferimento a queste variabili nella sezionecondition per controllare il rilevamento.

Esempio: filtrare in base allo scoring del rischio calcolato

Regola

Nella sezione condition, puoi utilizzare le variabili outcome definite nella sezione outcome. L'esempio seguente mostra come filtrare in base ai punteggi di rischio per ridurre il rumore nei rilevamenti utilizzando le condizioni dei risultati.

rule OutcomeConditionalRule {
meta:
  author = "alice@example.com"
  description = "Rule that uses outcome conditionals"

events:
  $u.metadata.event_type = "FILE_COPY"
  $u.principal.file.size = $file_size
  $u.principal.hostname = $hostname

  // 1 = Sunday, 7 = Saturday.
  $dayofweek = timestamp.get_day_of_week($u.metadata.collected_timestamp.seconds)

outcome:
  $risk_score =
      if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
      if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
      if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
      if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices

condition:
  $u and $risk_score >= 10
}

Cerca

metadata.event_type = "FILE_COPY"
principal.file.size = $file_size
principal.hostname = $hostname

// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.collected_timestamp.seconds)

outcome:
  $risk_score =
      if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
      if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
      if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
      if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices

Dashboard

Questa query aggiunge la variabile di risultato $hostname per visualizzare gli host associati a ogni scoring del rischio.

metadata.event_type = "FILE_COPY"
principal.file.size = $file_size
principal.hostname = $hostname

// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.collected_timestamp.seconds)

outcome:
  $host = $hostname
  $risk_score =
      if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
      if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
      if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
      if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices

Query per evento singolo con risultato

Caso d'uso: arricchisci i rilevamenti in un determinato momento con un contesto immediato, ad esempio assegnando tag di gravità in base a elenchi di utenti o attributi di file senza richiedere una finestra temporale o una correlazione degli eventi.

Logica chiave: utilizza la sezione outcome in una regola che non ha una sezione match. In questo modo puoi estrarre i metadati ed eseguire la logica condizionale (ad esempio, il controllo di un utente rispetto a un elenco di riferimento) per ogni singolo evento che soddisfa i criteri.

Esempio: tagging della gravità point-in-time

Regola

L'esempio seguente mostra come utilizzare la sezione outcome in una regola a evento singolo per impostare variabili per l'utilizzo downstream, ad esempio impostando un punteggio di gravità in base all'utente specifico e alle dimensioni del file coinvolti in un evento di copia del file.

rule OutcomeRuleSingleEvent {
meta:
  author = "alice@example.com"
events:
  $u.metadata.event_type = "FILE_COPY"
  $u.principal.file.size = $file_size
  $u.principal.hostname = $hostname

outcome:
  $suspicious_host = $hostname
  $admin_severity = if($u.principal.user.userid in %admin_users, "SEVERE", "MODERATE")
  $severity_tag = if($file_size > 1024, $admin_severity, "LOW")

condition:
  $u
}

Cerca

L'esempio seguente identifica gli eventi di creazione di file e utilizza la sezione outcome per assegnare dinamicamente i livelli di gravità a ogni risultato. A differenza delle regole multi-evento, questa ricerca non aggregata non richiede variabili evento o una sezione match. Al contrario, elabora ogni log singolarmente per generare 1 row per event, arricchito con una logica personalizzata basata sulle dimensioni del file e sulle autorizzazioni dell'utente.

metadata.event_type = "FILE_CREATION"
principal.file.size = $file_size
principal.hostname = $hostname

outcome:
  $suspicious_host = $hostname
  $admin_severity = if(principal.user.userid in %a1, "SEVERE", "MODERATE")
  $severity_tag = if($file_size > 1024, $admin_severity, "LOW")

Dashboard

Una variante della dashboard non è applicabile a questo esempio, poiché l'intento principale è taggare e arricchire i singoli eventi. Sebbene una dashboard possa aggregare questi eventi (ad esempio, calcolando il conteggio totale degli eventi per tag di gravità), ciò oscurerebbe i dettagli granulari a livello di riga che questa ricerca non aggregata è progettata per trovare.

Scoring del rischio basato sulla rete

Caso d'uso: identifica i trasferimenti di dati ad alto rischio calcolando il volume cumulativo del traffico di rete in un gruppo di eventi. In questo modo puoi identificare le minacce in cui la soglia di dati totale supera un limite specifico (ad esempio, 1024 byte), tenendo conto al contempo della gravità della vulnerabilità degli asset coinvolti.

Logica chiave: utilizza la funzione di aggregazione sum() nella sezione outcome per combinare sent_bytes e received_bytes in tutti gli eventi in una finestra match. Per le regole, la query utilizza un'istruzione if per applicare uno scoring del rischio più elevato se la somma supera una soglia definita.

Esempio: regola di scoring del rischio basata sulla rete

Regola

L'esempio seguente mostra come utilizzare la sezione outcome per calcolare uno scoring del rischio dinamico in base all'attività di rete. Sommando i byte totali trasferiti in un gruppo di eventi, la regola applica una priorità più alta alle corrispondenze che superano una soglia di dati specifica (1024 byte), tenendo conto contemporaneamente della gravità della vulnerabilità dell'asset coinvolto.

rule OutcomeRuleMultiEvent {
meta:
  author = "alice@example.com"
events:
  $u.udm.principal.hostname = $hostname
  $asset_context.graph.entity.hostname = $hostname

  $severity = $asset_context.graph.entity.asset.vulnerabilities.severity

match:
  $hostname over 5m

outcome:
  $total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)

  $risk_score = if($total_network_bytes > 1024, 100, 50) +
    max(
      if($severity = "HIGH", 10)
      + if($severity = "MEDIUM", 5)
      + if($severity = "LOW", 1)
    )

  $asset_id_list =
    array(
      if($u.principal.asset_id = "",
          "Empty asset id",
          $u.principal.asset_id
      )
    )

  $asset_id_distinct_list = array_distinct($u.principal.asset_id)

  $asset_id_count = count($u.principal.asset_id)

  $asset_id_distinct_count = count_distinct($u.principal.asset_id)

condition:
  $u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}

Cerca

L'esempio seguente mostra una variante di ricerca che correla gli eventi di rete UDM con il contesto degli asset del grafico del contesto delle entità (ECG). Utilizza una finestra match di 5 minuti per aggregare il traffico di rete in base al nome host, calcola uno scoring del rischio in base al volume dei dati e alla gravità della vulnerabilità e applica un filtro condizionale per escludere ID asset specifici dal set di risultati finale.

$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname

$severity = $asset_context.graph.entity.asset.vulnerabilities.severity

match:
  $hostname over 5m

outcome:
  $total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)

  $risk_score = if($total_network_bytes > 1024, 100, 50) +
    max(
      if($severity = "HIGH", 10)
      + if($severity = "MEDIUM", 5)
      + if($severity = "LOW", 1)
    )

  $asset_id_list =
    array(
      if($u.principal.asset_id = "",
        "Empty asset id",
        $u.principal.asset_id
      )
    )

  $asset_id_distinct_list = array_distinct($u.principal.asset_id)

  $asset_id_count = count($u.principal.asset_id)

  $asset_id_distinct_count = count_distinct($u.principal.asset_id)

condition:
  $u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")

Dashboard

Il seguente esempio illustra una variante di Dashboard che arricchisce la telemetria di rete in tempo reale con i dati sulle vulnerabilità degli asset. Abbinando i nomi host in una finestra temporale di 5 minuti, questa query consente agli sviluppatori di creare widget della dashboard che visualizzano i livelli di rischio degli asset. La logica regola dinamicamente uno scoring del rischio in base al throughput della rete e alla vulnerabilità con la gravità più elevata rilevata nell'asset, fornendo una visualizzazione con priorità dei sistemi potenzialmente compromessi.

$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname

$severity = $asset_context.graph.entity.asset.vulnerabilities.severity

match:
  $hostname over 5m

outcome:
  $total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)

  $risk_score = if($total_network_bytes > 1024, 100, 50) +
    max(
      if($severity = "HIGH", 10)
      + if($severity = "MEDIUM", 5)
      + if($severity = "LOW", 1)
    )

  $asset_id_list =
    array(
      if($u.principal.asset_id = "",
        "Empty asset id",
        $u.principal.asset_id
      )
    )

  $asset_id_distinct_list = array_distinct($u.principal.asset_id)

  $asset_id_count = count($u.principal.asset_id)

  $asset_id_distinct_count = count_distinct($u.principal.asset_id)

condition:
  $u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")

Refactoring di una regola multi-evento outcome (pre-refactoring)

Caso d'uso: migliora le prestazioni del sistema e riduci la latenza di elaborazione convertendo le regole per più eventi in regole per eventi singoli. Questa opzione è ideale per le regole originariamente progettate con una sezione di corrispondenza solo per abilitare la sezione dei risultati, ma che in realtà non richiedono la correlazione tra più eventi distinti.

Logica chiave: rimuove la sezione match e qualsiasi funzione aggregata (ad esempio max(), sum() o count()) dalla sezione outcome. Questa transizione sposta la regola dal raggruppamento degli eventi nel tempo alla valutazione di ogni evento singolarmente man mano che arriva. match) e le regole multi-evento (regole con una sezione match).

Puoi utilizzare la sezione outcome sia per le regole per un singolo evento (regole senza una sezione match) sia per le regole per più eventi. Se in precedenza hai progettato una regola per più eventi solo per poter utilizzare la sezione dei risultati, puoi facoltativamente rifattorizzare queste regole eliminando la sezione match per migliorare le prestazioni. Tieni presente che, poiché la regola non ha più una sezione match che applica il raggruppamento, potresti ricevere più rilevamenti.

Esempio: rifattorizzazione dei risultati (pre-rifattorizzazione)

Regola

L'esempio seguente mostra una regola di risultato per più eventi che utilizza una sola variabile di evento. Poiché utilizza una sezione match, il motore di regole deve raggruppare gli eventi in un intervallo di 5 minuti prima di calcolare il risultato, il che consuma più risorse rispetto a una valutazione di un singolo evento.

rule OutcomeMultiEventPreRefactor {
meta:
  author = "alice@example.com"
  description = "Outcome refactor rule, before the refactor"

events:
  $u.udm.principal.hostname = $hostname

match:
  $hostname over 5m

outcome:
  $risk_score = max(if($hostname = "my-hostname", 100, 50))

condition:
  $u
}

Cerca

Query equivalente per le statistiche

events:
  $u.udm.principal.hostname = $hostname

match:
  $hostname over 5m

outcome:
  $risk_score = max(if($hostname = "my-hostname", 100, 50))

condition:
  $u

Dashboard

events:
  $u.udm.principal.hostname = $hostname

match:
  $hostname over 5m

outcome:
  $risk_score = max(if($hostname = "my-hostname", 100, 50))

condition:
  $u

Eseguire il refactoring di una regola multi-evento outcome (post-refactoring)

Caso d'uso: finalizzazione dell'ottimizzazione di una query per migliorare la velocità di elaborazione. Rimuovendo il requisito di raggruppamento, la query ora attiva un rilevamento immediatamente all'arrivo di un singolo evento corrispondente, il che è molto più efficiente per il motore delle regole.

Logica chiave: elimina la sezione match e rimuove la funzione aggregate (ad esempio max()) dall'assegnazione della variabile outcome. La logica all'interno dell'istruzione if rimane invariata, ma ora viene applicata a un singolo evento anziché a un gruppo.

Puoi eseguire il refactoring della query eliminando la sezione match. Nota: devi rimuovere anche l'aggregazione nella sezione outcome perché la query ora è un singolo evento. Per ulteriori informazioni sulle aggregazioni, consulta Aggregazioni dei risultati.

Esempio: refactoring del risultato

Regola

rule OutcomeSingleEventPostRefactor {
meta:
  author = "alice@example.com"
  description = "Outcome refactor rule, after the refactor"

events:
  $u.udm.principal.hostname = $hostname

// We deleted the match section.

outcome:
  // We removed the max() aggregate.
  $risk_score = if($hostname = "my-hostname", 100, 50)

condition:
  $u
}

Cerca

events:
  $u.udm.principal.hostname = $hostname

outcome:
  $risk_score = if($hostname = "my-hostname", 100, 50)

Dashboard

events:
  $u.udm.principal.hostname = $hostname

outcome:
  $risk_score = if($hostname = "my-hostname", 100, 50)

Assegnazione della funzione al segnaposto

Caso d'uso: normalizza i dati (ad esempio, standardizza i domini email) per verificare che il raggruppamento nella sezione delle corrispondenze sia accurato.

Logica chiave: assegna il risultato di re.capture() o strings.concat() a una variabile segnaposto.

Esempio: assegnazione di variabili da funzione a segnaposto

Puoi assegnare una variabile segnaposto al risultato di una chiamata di funzione e utilizzarla in altre sezioni della regola, ad esempio nelle sezioni match, outcome o condition.

Regola

rule FunctionToPlaceholderRule {
meta:
  author = "alice@example.com"
  description = "Rule that uses function to placeholder assignments"

events:
  $u.metadata.event_type = "EMAIL_TRANSACTION"

  // Use function-placeholder assignment to extract the
  // address from an email.
  // address@website.com -> address
  $email_to_address_only = re.capture($u.network.email.to , "(.*)@")

  // Use function-placeholder assignment to normalize an email:
  // address@-> address@company.com
  $email_from_normalized = strings.concat(
      re.capture($u.network.email.from , "(.*)@"),
      "@company.com"
  )

  // Use function-placeholder assignment to get the day of the week of the event.
  // 1 = Sunday, 7 = Saturday.
  $dayofweek = timestamp.get_day_of_week($u.metadata.event_timestamp.seconds)

match:
  // Use placeholder (from function-placeholder assignment) in match section.
  // Group by the normalized from email, and expose it in the detection.
  $email_from_normalized over 5m

outcome:
  // Use placeholder (from function-placeholder assignment) in outcome section.
  // Assign more risk if the event happened on weekend.
  $risk_score = max(
      if($dayofweek = 1 or $dayofweek = 7, 10, 0)
  )

condition:
  // Use placeholder (from function-placeholder assignment) in condition section.
  // Match if an email was sent to multiple addresses.
  #email_to_address_only > 1
}

Cerca

metadata.event_type = "EMAIL_TRANSACTION"

// Use function-placeholder assignment to extract the
// address from an email.
// address@website.com -> address
$email_to_address_only = re.capture(network.email.from , "(.*)@")

// Use function-placeholder assignment to normalize an email:
// address@??? -> address@company.com
$email_from_normalized = strings.concat(
  re.capture(network.email.to , "(.*)@"),
  "@company.com"
  )

// Use function-placeholder assignment to get the day of the week of the event.
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.event_timestamp.seconds)

match:
  // Use placeholder (from function-placeholder assignment) in match section.
  // Group by the normalized from email, and expose it in the detection.
  $email_from_normalized over 5m

outcome:
  // Use placeholder (from function-placeholder assignment) in outcome section.
  // Assign more risk if the event happened on weekend.
  $risk_score = max(
    if($dayofweek = 1 or $dayofweek = 7, 10, 0)
    )

condition:
  // Use placeholder (from function-placeholder assignment) in condition section.
  // Match if an email was sent to multiple addresses.
  #email_to_address_only > 1

Dashboard

L'esempio seguente mostra una variante di Dashboards ottimizzata per la visualizzazione di serie temporali. Utilizzando una finestra a cascata di un giorno, anziché una granularità a livello di minuti, questa query produce punti dati stabili e non sovrapposti, ideali per rappresentare graficamente lo scoring del rischio in un periodo di tempo prolungato. La logica normalizza le entità email e applica ponderazioni di rischio più elevate alle transazioni del fine settimana, fornendo una tendenza giornaliera chiara dell'attività email sospetta per il monitoraggio a lungo termine.

metadata.event_type = "EMAIL_TRANSACTION"

// Use function-placeholder assignment to extract the
// address from an email.
// address@website.com -> address
$email_to_address_only = re.capture(network.email.from , "(.*)@")

// Use function-placeholder assignment to normalize an email:
// address@??? -> address@company.com
$email_from_normalized = strings.concat(
re.capture(network.email.to , "(.*)@"),
"@company.com"
)

// Use function-placeholder assignment to get the day of the week of the event.
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.event_timestamp.seconds)

match:
// Use placeholder (from function-placeholder assignment) in match section.
// Group by the normalized from email, and expose it in the detection.
$email_from_normalized over 5m

outcome:
// Use placeholder (from function-placeholder assignment) in outcome section.
// Assign more risk if the event happened on weekend.
$risk_score = max(
  if($dayofweek = 1 or $dayofweek = 7, 10, 0)
  )

condition:
// Use placeholder (from function-placeholder assignment) in condition section.
// Match if an email was sent to multiple addresses.
#email_to_address_only > 1

Ottimizzazione e filtri

L'ottimizzazione efficace delle regole si basa su un filtraggio preciso dei dati per garantire che il motore di rilevamento elabori solo informazioni significative. Escludendo i dati "rumorosi" o incompleti, puoi migliorare significativamente il rendimento delle regole e assicurarti che gli avvisi generati siano azionabili.

Argomento Esempi
Esclusione dei valori pari a zero Esclusione esplicita e implicita del valore zero

Esclusione dei valori zero

Caso d'uso: assicurati dell'accuratezza delle regole e riduci i falsi positivi filtrando esplicitamente le stringhe vuote, i valori null o gli account segnaposto generici (ad esempio "Ospite") che non forniscono dati di sicurezza utilizzabili.

Logica chiave: sfrutta il filtro implicito dei valori zero per le variabili utilizzate nella sezione match del motore di regole, utilizzando operatori di disuguaglianza espliciti (!= "") per altri campi evento per assicurarsi che solo i dati compilati attivino un rilevamento.

Il motore delle regole filtra implicitamente i valori pari a zero per tutti i segnaposto utilizzati nella sezione match. Utilizza l'opzione allow_zero_values per disattivarlo. Tuttavia, per gli altri campi evento a cui viene fatto riferimento, i valori pari a zero non vengono esclusi, a meno che tu non specifichi esplicitamente queste condizioni. Per saperne di più, consulta la sezione Valori zero nella sezione di corrispondenza.

Esempio: esclusione del valore zero esplicito e implicito

Regola

rule ExcludeZeroValues {
meta:
  author = "alice@example.com"

events:
  $e1.metadata.event_type = "NETWORK_DNS"
  $e1.principal.hostname = $hostname

  // $e1.principal.user.userid may be empty string.
  $e1.principal.user.userid != "Guest"

  $e2.metadata.event_type = "NETWORK_HTTP"
  $e2.principal.hostname = $hostname

  // $e2.target.asset_id cannot be empty string as explicitly specified.
  $e2.target.asset_id != ""

match:
  // $hostname cannot be empty string. The rule behaves as if the
  // predicate, `$hostname != ""` was added to the events section, because
  // `$hostname` is used in the match section.
  $hostname over 1h

condition:
  $e1 and $e2
}

Cerca

Devi dichiarare esplicitamente che hostname non può essere una stringa vuota, in quanto non esiste un filtro implicito con valore zero per i segnaposto nella sezione match.

$e1.metadata.event_type = "NETWORK_DNS"
$e1.principal.hostname = $hostname

// $e1.principal.user.userid may be empty string.
$e1.principal.user.userid != "Guest"

$e2.metadata.event_type = "NETWORK_HTTP"
$e2.principal.hostname = $hostname

// $e2.target.asset_id and hostname cannot be empty string as explicitly specified.
$e2.target.asset_id != ""
$hostname != ""

match:
  $hostname over 1h

Dashboard

Devi dichiarare esplicitamente che hostname non può essere una stringa vuota, in quanto non esiste un filtro implicito con valore zero per i segnaposto nella sezione match.

$e1.metadata.event_type = "NETWORK_DNS"
$e1.principal.hostname = $hostname

// $e1.principal.user.userid may be empty string.
$e1.principal.user.userid != "Guest"

$e2.metadata.event_type = "NETWORK_HTTP"
$e2.principal.hostname = $hostname

// $e2.target.asset_id and hostname cannot be empty string as explicitly specified.
$e2.target.asset_id != ""
$hostname != ""

match:
  $hostname over 1h

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