Panoramica dell'analisi dei log
Questo documento fornisce una panoramica di come Google Security Operations analizza i log non elaborati nel formato Unified Data Model (UDM).
Google Security Operations può ricevere dati di log provenienti dalla seguente importazione fonti:
- Inoltratore di Google Security Operations
- Feed dell'API Google Security Operations
- API Google Security Operations Ingestion
- Partner tecnologico di terze parti
In generale, i clienti inviano i dati come log non elaborati originali. Google Security Operations in modo univoco identifica il dispositivo che ha generato i log utilizzando il valore LogType. Il tipo di log identifica entrambi:
- il fornitore e il dispositivo che ha generato il log, ad esempio Cisco Firewall, Server DHCP Linux o Bro DNS.
- quale parser converte il log non elaborato in un modello di dati unificato (UDM) strutturato. Esiste una relazione one-to-one tra un parser e un LogType. Ogni parser converte i dati ricevuti da un singolo LogType.
Google Security Operations fornisce un set di parser predefiniti che leggono i log originali non elaborati e generare record UDM strutturati utilizzando i dati del log non elaborato originale. Operazioni di sicurezza di Google gestisce questi parser. I clienti possono anche definire istruzioni personalizzate per la mappatura dei dati creando un parser specifico del cliente. Contatta il tuo team Google Security Operations per informazioni sulla creazione di un parser specifico per il cliente.
Il parser contiene istruzioni per la mappatura dei dati. Definisce il modo in cui i dati vengono mappati dal log non elaborato originale a uno o più campi nella struttura dei dati UDM.
Se non sono presenti errori di analisi, Google Security Operations crea un record strutturato UDM utilizzando i dati del log non elaborato. Il processo di conversione di un log non elaborato in un record UDM chiamata normalizzazione.
Un parser predefinito potrebbe mappare un sottoinsieme di valori principali dal log non elaborato. In genere, Questi campi sono i più importanti per fornire insight sulla sicurezza Google Security Operations. I valori non mappati rimangono nel log non elaborato, ma non vengono archiviati nel record UDM.
Un cliente può anche utilizzare l'API Ingestion, per inviare dati in formato UDM (Unified Data Model).
Personalizza la modalità di analisi dei dati importati
Google Security Operations fornisce le seguenti funzionalità che consentono ai clienti di personalizzare l'analisi dei dati di log originali in arrivo.
- Parser specifici del cliente: i clienti creano un parser personalizzato configurazione per un tipo di log specifico che soddisfa le i tuoi requisiti. Un parser specifico del cliente sostituisce il parser predefinito per lo specifico LogType. Contatta il tuo team Google Security Operations per informazioni sulla creazione di un parser specifico per il cliente.
- Estensioni parser: i clienti possono aggiungere istruzioni di mappatura personalizzate in oltre alla configurazione predefinita del parser. Ogni cliente può creare il proprio insieme univoco di istruzioni di mappatura personalizzate. Questi mapping le istruzioni definiscono come estrarre e trasformare campi aggiuntivi dai log originali non elaborati in campi UDM. L'estensione parser non sostituisce parser predefinito o specifico del cliente.
Esempio di utilizzo di un log del proxy web Squid
Questa sezione fornisce un esempio di log del proxy web Squid e descrive come vengono mappati a un record UDM. Per una descrizione di tutti i campi nello schema UDM, consulta l'articolo Elenco dei campi del modello dei dati unificato.
L'esempio di log del proxy web Squid contiene valori separati da spazi. Ogni record rappresenta un evento e archivia i seguenti dati: timestamp, durata, client codice dei risultati/stato dei risultati, byte trasmessi, metodo di richiesta, URL, utente codice gerarchico e tipo di contenuti. In questo esempio, i campi seguenti sono estratti e mappati in un record UDM: ora, client, stato dei risultati, byte metodo di richiesta e URL.
1588059648.129 23 192.168.23.4 TCP_HIT/200 904 GET www.google.com/images/sunlogo.png - HIER_DIRECT/203.0.113.52 image/jpeg
Confrontando queste strutture, nota che solo un sottoinsieme della i dati di log sono inclusi nel record UDM. Alcuni campi sono obbligatori, mentre altri sono facoltativi. Inoltre, solo un sottoinsieme delle sezioni del record UDM contengono dati. Se il parser non mappa i dati del log originale all'UDM non vedrai quella sezione del record UDM in Google Security Operations.
La sezione metadata
memorizza il timestamp dell'evento. Come puoi notare, il valore è stato convertito
da EPOCH al formato RFC 3339. Questa conversione è facoltativa. Il timestamp può essere
memorizzati in formato EPOCH, con pre-elaborazione per separare i secondi e
di millisecondi in campi separati.
La metadata.event_type
memorizza il valore NETWORK_HTTP
che è un valore enumerato
che identifica il tipo di evento. Il valore dell'attributo metadata.event_type
determina
quali campi UDM aggiuntivi sono obbligatori e facoltativi. Le product_name
e
I valori vendor_name
contengono descrizioni semplici del dispositivo che
registrato il log originale.
Il valore metadata.event_type
in un record di eventi UDM non corrisponde a log_type
durante l'importazione dei dati
tramite l'API Ingestion. Questi due attributi memorizzano
informazioni diverse.
La sezione network
contiene i valori dell'evento di log originale. Nota in questo
esempio che il valore dello stato del log originale è stato analizzato dai risultati
code/status" prima di essere scritto nel record UDM. Solo il valore result_code
è stato incluso nel record UDM.
Nella sezione principal
vengono archiviate le informazioni sul client del log originale. La
Nella sezione target
vengono archiviati sia l'URL completo sia l'indirizzo IP.
La sezione security_result
memorizza uno dei valori enum per rappresentare l'azione registrata nel log originale.
Si tratta del record UDM formattato come JSON. Nota che solo le sezioni che
contengono dati. src
, observer
, intermediary
, about
,
e extensions
non sono incluse.
{
"metadata": {
"event_timestamp": "2020-04-28T07:40:48.129Z",
"event_type": "NETWORK_HTTP",
"product_name": "Squid Proxy",
"vendor_name": "Squid"
},
"principal": {
"ip": "192.168.23.4"
},
"target": {
"url": "www.google.com/images/sunlogo.png",
"ip": "203.0.113.52"
},
"network": {
"http": {
"method": "GET",
"response_code": 200,
"received_bytes": 904
}
},
"security_result": {
"action": "UNKNOWN_ACTION"
}
}
Passaggi nelle istruzioni del parser
Le istruzioni per la mappatura dei dati all'interno di un parser seguono uno schema comune, che segue:
- Analizza ed estrai i dati dal log originale.
- Manipolare i dati estratti. È incluso l'uso della logica condizionale per analizzare selettivamente i valori, convertire i tipi di dati, sostituire sottostringhe , convertire in maiuscolo o minuscolo e così via.
- Assegna valori ai campi UDM.
- Restituisce il record UDM mappato nella chiave @output.
Analizza ed estrai i dati dal log originale
Impostare l'istruzione di filtro
L'istruzione filter
è la prima istruzione nel set di istruzioni di analisi.
Tutte le istruzioni di analisi aggiuntive sono contenute nell'istruzione filter
.
filter {
}
Inizializza le variabili in cui verranno archiviati i valori estratti
All'interno dell'istruzione filter
, inizializza le variabili intermedie che
il parser userà per archiviare i valori estratti dal log.
Queste variabili vengono utilizzate ogni volta che viene analizzato un singolo log. Il valore in ogni variabile intermedia verrà impostata su uno o più campi UDM più avanti nella le istruzioni di analisi.
mutate {
replace => {
"event.idm.read_only_udm.metadata.product_name" => "Webproxy"
"event.idm.read_only_udm.metadata.vendor_name" => "Squid"
"not_valid_log" => "false"
"when" => ""
"srcip" => ""
"action" => ""
"username" => ""
"url" => ""
"tgtip" => ""
"method" => ""
}
}
Estrarre singoli valori dal log
Google Security Operations fornisce un insieme di filtri, basati su Logstash, per estrarre i campi dai file di log originali. A seconda del formato del log, puoi utilizzare uno o più filtri di estrazione per estrarre tutti i dati dal log. Se la stringa è:
- JSON nativo, la sintassi del parser è simile Filtro JSON, che supporta i log in formato JSON. Il file JSON nidificato non è supportato.
- XML, la sintassi del parser è simile a Filtro XML che supporta i log in formato XML.
- coppie chiave-valore, la sintassi del parser è simile alla Filtro Kv, che supporta i messaggi in formato chiave-valore.
- CSV, la sintassi del parser è simile a Filtro CSV che supporta i messaggi in formato CSV.
- in tutti gli altri formati, la sintassi del parser è simile Filtro GROK con pattern integrati GROK . Vengono utilizzate le istruzioni per l'estrazione in stile regex.
Google Security Operations fornisce un sottoinsieme delle funzionalità disponibili in ogni filtro. Google Security Operations fornisce anche una sintassi di mappatura dei dati personalizzata non disponibile nei filtri. Consulta il Riferimento per la sintassi dell'analizzatore per una descrizione delle funzionalità supportate e delle funzioni personalizzate.
Continuando con l'esempio di log del proxy web Squid, la seguente estrazione di dati include una combinazione della sintassi Grok di Logstash e di le espressioni regolari.
La seguente istruzione di estrazione archivia i valori nel seguente intermedio variabili:
when
srcip
action
returnCode
size
method
username
url
tgtip
Questa istruzione di esempio utilizza anche la parola chiave overwrite
per archiviare i valori estratti
in ogni variabile. Se il processo di estrazione restituisce un errore, l'elemento on_error
imposta not_valid_log
su True
.
grok {
match => {
"message" => [
"%{NUMBER:when}\\s+\\d+\\s%{SYSLOGHOST:srcip} %{WORD:action}\\/%{NUMBER:returnCode} %{NUMBER:size} %{WORD:method} (?P<url>\\S+) (?P<username>.*?) %{WORD}\\/(?P<tgtip>\\S+).*"
]
}
overwrite => ["when","srcip","action","returnCode","size","method","url","username","tgtip"]
on_error => "not_valid_log"
}
Manipolare e trasformare i valori estratti
Google Security Operations sfrutta le funzionalità del plug-in filtro mutate di Logstash per consentire la manipolazione dei valori estratti dal log originale. Google Security Operations fornisce un sottoinsieme delle funzionalità disponibili nel plug-in. Per una descrizione delle funzionalità, consulta la sintassi dell'analizzatore sintattico. supportate e personalizzate, ad esempio:
- trasmette i valori a un tipo di dati diverso
- sostituisci i valori nella stringa
- unisci due array o aggiungi una stringa a un array. I valori delle stringhe sono in un array prima dell'unione.
- converti in lettere minuscole o maiuscole
Questa sezione fornisce esempi di trasformazione dei dati che si basano sul log del proxy web Squid presentati in precedenza.
Trasforma il timestamp dell'evento
Tutti gli eventi archiviati come record UDM devono avere un timestamp evento. Questo esempio
verifica se un valore per i dati è stato estratto dal log. Quindi utilizza
Funzione di data Grok
per abbinare il valore al formato dell'ora UNIX
.
if [when] != "" {
date {
match => [
"when", "UNIX"
]
}
}
Trasforma il valore username
La seguente istruzione di esempio converte il valore nella variabile username
in minuscolo.
mutate {
lowercase => [ "username"]
}
Trasforma il valore action
L'esempio seguente valuta il valore nella variabile intermedia action
e cambia il valore in ALLOW, BLOCK o UNKNOWN_ACTION, che sono
valori validi per il campo UDM security_result.action
. L'UDM di security_result.action
è un tipo enumerato che archivia solo valori specifici.
if ([action] == "TCP_DENIED" or [action] == "TCP_MISS" or [action] == "Denied" or [action] == "denied" or [action] == "Dropped") {
mutate {
replace => {
"action" => "BLOCK"
}
}
} else if ([action] == "TCP_TUNNEL" or [action] == "Accessed" or [action] == "Built" or [action] == "Retrieved" or [action] == "Stored") {
mutate {
replace => {
"action" => "ALLOW"
}
}
} else {
mutate {
replace => {
"action" => "UNKNOWN_ACTION" }
}
}
Trasforma l'indirizzo IP di destinazione
L'esempio seguente verifica la presenza di un valore nella variabile intermedia tgtip
.
Se trovato, il valore viene abbinato a un pattern di indirizzi IP utilizzando un elenco Grok predefinito
pattern. Se si verifica un errore di corrispondenza del valore a un pattern di indirizzi IP, il valore
La funzione on_error
imposta la proprietà not_valid_tgtip
su True
. Se la corrispondenza
ha esito positivo, la proprietà not_valid_tgtip
non è impostata.
if [tgtip] not in [ "","-" ] {
grok {
match => {
"tgtip" => [ "%{IP:tgtip}" ]
}
overwrite => ["tgtip"]
on_error => "not_valid_tgtip"
}
Modificare il tipo di dati di ReturnCode e la dimensione
Nell'esempio seguente il valore nella variabile size
viene trasmesso a
uinteger
e il valore nella variabile returnCode
su integer
. Questo è
obbligatorio perché la variabile size
verrà salvata nella
network.received_bytes
Campo UDM che memorizza un tipo di dati int64
. La
returnCode
variabile verrà salvata nel campo UDM network.http.response_code
che archivia un tipo di dati int32
.
mutate {
convert => {
"returnCode" => "integer"
"size" => "uinteger"
}
}
Assegnare valori ai campi UDM in un evento
Dopo che i valori sono stati estratti e pre-elaborati, assegnali ai campi in un UDM un record di eventi. Puoi assegnare sia valori estratti che statici a un campo UDM.
Se compili event.disambiguation_key
, assicurati che questo campo sia univoco per
ogni evento generato per il log specificato. Se due eventi diversi hanno
stesso disambiguation_key
, questo comporterà un comportamento imprevisto nel
di un sistema operativo completo.
Gli esempi di parser in questa sezione si basano sull'esempio di log del proxy web Squid in alto.
Salva il timestamp dell'evento
Ogni record di eventi UDM deve avere un valore impostato per metadata.event_timestamp
campo UDM. L'esempio seguente salva il timestamp dell'evento estratto dal log nel
@timestamp
variabile integrata. Google Security Operations salva il file nel
metadata.event_timestamp
Campo UDM per impostazione predefinita.
mutate {
rename => {
"when" => "timestamp"
}
}
Impostare il tipo di evento
Ogni record di eventi UDM deve avere un valore impostato per l'UDM metadata.event_type
. Questo campo è di tipo enumerato. Il valore di questo campo determina
quali campi UDM aggiuntivi devono essere compilati per salvare il record UDM.
Il processo di analisi e normalizzazione avrà esito negativo se uno dei campi obbligatori viene eseguito
non contengono dati validi.
replace => {
"event.idm.read_only_udm.metadata.event_type" => "NETWORK_HTTP"
}
}
Salva i valori username
e method
utilizzando l'istruzione replace
I valori nei campi intermedi username
e method
sono stringhe. La
L'esempio seguente verifica se esiste un valore valido e, in caso affermativo, archivia
il valore username
al campo UDM principal.user.userid
e al campo method
al campo UDM network.http.method
.
if [username] not in [ "-" ,"" ] {
mutate {
replace => {
"event.idm.read_only_udm.principal.user.userid" => "%{username}"
}
}
}
if [method] != "" {
mutate {
replace => {
"event.idm.read_only_udm.network.http.method" => "%{method}"
}
}
}
Salva action
nel campo UDM security_result.action
Nella sezione precedente, il valore della variabile intermedia action
era
Vengono valutati e trasformati in uno dei valori standard per il campo UDM security_result.action
.
Entrambi i campi UDM security_result
e action
memorizzano un array di elementi,
il che significa che dovrai seguire un approccio leggermente diverso quando salvi
valore.
Innanzitutto, salva il valore trasformato in un intermediario security_result.action
. Il campo security_result
è un padre del campo action
.
mutate {
merge => {
"security_result.action" => "action"
}
}
Quindi, salva il campo intermedio security_result.action
intermedio nel campo
security_result
campo UDM. Il campo UDM security_result
archivia un array di
, in modo che il valore venga aggiunto a questo campo.
# save the security_result field
mutate {
merge => {
"event.idm.read_only_udm.security_result" => "security_result"
}
}
Archivia l'indirizzo IP di destinazione e l'indirizzo IP di origine utilizzando l'istruzione merge
Archivia i seguenti valori nel record di eventi UDM:
- Valore nella variabile intermedia
srcip
nel campo UDMprincipal.ip
. - Valore nella variabile intermedia
tgtip
nel campo UDMtarget.ip
.
Entrambi i campi UDM principal.ip
e target.ip
memorizzano un array di elementi, quindi
vengono aggiunti a ciascun campo.
Gli esempi riportati di seguito mostrano diversi approcci per salvare questi valori.
Durante la fase di trasformazione, la tgtip
variabile intermedia è stata abbinata a una
Indirizzo IP con un pattern Grok predefinito. La seguente dichiarazione di esempio
controlla se la proprietà not_valid_tgtip
è vera, indicando che tgtip
non è stato possibile trovare un valore corrispondente a un pattern di indirizzi IP. Se è false, salva la
tgtip
al campo UDM target.ip
.
if ![not_valid_tgtip] {
mutate {
merge => {
"event.idm.read_only_udm.target.ip" => "tgtip"
}
}
}
La variabile intermedia srcip
non è stata trasformata. La seguente dichiarazione
verifica se un valore è stato estratto dal log originale e, in caso affermativo, salva i salvataggi
il valore al campo UDM principal.ip
.
if [srcip] != "" {
mutate {
merge => {
"event.idm.read_only_udm.principal.ip" => "srcip"
}
}
}
Risparmia url
, returnCode
e size
usando l'istruzione rename
L'istruzione di esempio riportata di seguito archivia i seguenti valori utilizzando l'istruzione rename
.
- Variabile
url
salvata nel campo UDMtarget.url
. - La variabile intermedia
returnCode
salvata nel campo UDMnetwork.http.response_code
. - La variabile intermedia
size
salvata nel campo UDMnetwork.received_bytes
.
mutate {
rename => {
"url" => "event.idm.read_only_udm.target.url"
"returnCode" => "event.idm.read_only_udm.network.http.response_code"
"size" => "event.idm.read_only_udm.network.received_bytes"
}
}
Associa il record UDM all'output
L'istruzione finale dell'istruzione di mappatura dei dati restituisce i dati elaborati in un record di eventi UDM.
mutate {
merge => {
"@output" => "event"
}
}
Il codice completo del parser
Questo è l'esempio di codice completo del parser. L'ordine delle istruzioni non segue le nello stesso ordine delle sezioni precedenti di questo documento, ma restituisce lo stesso output.
filter {
# initialize variables
mutate {
replace => {
"event.idm.read_only_udm.metadata.product_name" => "Webproxy"
"event.idm.read_only_udm.metadata.vendor_name" => "Squid"
"not_valid_log" => "false"
"when" => ""
"srcip" => ""
"action" => ""
"username" => ""
"url" => ""
"tgtip" => ""
"method" => ""
}
}
# Extract fields from the raw log.
grok {
match => {
"message" => [
"%{NUMBER:when}\\s+\\d+\\s%{SYSLOGHOST:srcip} %{WORD:action}\\/%{NUMBER:returnCode} %{NUMBER:size} %{WORD:method} (?P<url>\\S+) (?P<username>.*?) %{WORD}\\/(?P<tgtip>\\S+).*"
]
}
overwrite => ["when","srcip","action","returnCode","size","method","url","username","tgtip"]
on_error => "not_valid_log"
}
# Parse event timestamp
if [when] != "" {
date {
match => [
"when", "UNIX"
]
}
}
# Save the value in "when" to the event timestamp
mutate {
rename => {
"when" => "timestamp"
}
}
# Transform and save username
if [username] not in [ "-" ,"" ] {
mutate {
lowercase => [ "username"]
}
}
mutate {
replace => {
"event.idm.read_only_udm.principal.user.userid" => "%{username}"
}
}
if ([action] == "TCP_DENIED" or [action] == "TCP_MISS" or [action] == "Denied" or [action] == "denied" or [action] == "Dropped") {
mutate {
replace => {
"action" => "BLOCK"
}
}
} else if ([action] == "TCP_TUNNEL" or [action] == "Accessed" or [action] == "Built" or [action] == "Retrieved" or [action] == "Stored") {
mutate {
replace => {
"action" => "ALLOW"
}
}
} else {
mutate {
replace => {
"action" => "UNKNOWN_ACTION" }
}
}
# save transformed value to an intermediary field
mutate {
merge => {
"security_result.action" => "action"
}
}
# save the security_result field
mutate {
merge => {
"event.idm.read_only_udm.security_result" => "security_result"
}
}
# check for presence of target ip. Extract and store target IP address.
if [tgtip] not in [ "","-" ] {
grok {
match => {
"tgtip" => [ "%{IP:tgtip}" ]
}
overwrite => ["tgtip"]
on_error => "not_valid_tgtip"
}
# store target IP address
if ![not_valid_tgtip] {
mutate {
merge => {
"event.idm.read_only_udm.target.ip" => "tgtip"
}
}
}
}
# convert the returnCode and size to integer data type
mutate {
convert => {
"returnCode" => "integer"
"size" => "uinteger"
}
}
# save url, returnCode, and size
mutate {
rename => {
"url" => "event.idm.read_only_udm.target.url"
"returnCode" => "event.idm.read_only_udm.network.http.response_code"
"size" => "event.idm.read_only_udm.network.received_bytes"
}
# set the event type to NETWORK_HTTP
replace => {
"event.idm.read_only_udm.metadata.event_type" => "NETWORK_HTTP"
}
}
# validate and set source IP address
if [srcip] != "" {
mutate {
merge => {
"event.idm.read_only_udm.principal.ip" => "srcip"
}
}
}
# save event to @output
mutate {
merge => {
"@output" => "event"
}
}
} #end of filter