Panoramica dell'analisi dei log

Supportato in:

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.

Flusso di lavoro di importazione e normalizzazione

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

Esempio di proxy web Squid

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.

Valori di log mappati a UDM

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.

Valori di log mappati a 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:

  1. Analizza ed estrai i dati dal log originale.
  2. 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.
  3. Assegna valori ai campi UDM.
  4. 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 UDM principal.ip.
  • Valore nella variabile intermedia tgtip nel campo UDM target.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 tgtipvariabile 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 UDM target.url.
  • La variabile intermedia returnCode salvata nel campo UDM network.http.response_code.
  • La variabile intermedia size salvata nel campo UDM network.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