Descripción general del análisis de registros

Se admite en los siguientes países:

En este documento, se proporciona una descripción general de cómo Google Security Operations analiza los registros sin procesar en el formato del modelo de datos unificados (UDM).

Google Security Operations puede recibir datos de registro que se originan de la siguiente transferencia fuentes:

  • Reenviador de Google Security Operations
  • Feed de la API de Google Security Operations
  • API de transferencia de Google Security Operations
  • Socio tecnológico externo

En general, los clientes envían datos como registros originales sin procesar. Google Security Operations identifica de forma única el dispositivo que generó los registros con el LogType. LogType identifica lo siguiente:

  • el proveedor y el dispositivo que generó el registro, como Cisco Firewall, Linux DHCP Server o Bro DNS.
  • que convierte el registro sin procesar en un modelo de datos unificados (UDM) estructurado. Existe una relación uno a uno entre un analizador y un LogType. Cada analizador convierte los datos recibidos por un solo LogType.

Google Security Operations proporciona un conjunto de analizadores predeterminados que leen los registros originales sin procesar y generar registros de UDM estructurados con datos en el registro original sin procesar. Google Security Operations mantiene estos analizadores. Los clientes también pueden definir instrucciones personalizadas de asignación de datos creando un analizador específico del cliente. Comunícate con Google Security Operations representante para obtener información sobre la creación de un analizador específico del cliente.

Flujo de trabajo de transferencia y normalización

El analizador contiene instrucciones de asignación de datos. Define cómo se asignan los datos del registro original sin procesar a uno o más campos en la estructura de datos de UDM.

Si no hay errores de análisis, Google Security Operations crea un registro estructurado por UDM con a partir del registro sin procesar. El proceso de convertir un registro sin procesar en un registro UDM es llamada normalización.

Un analizador predeterminado puede asignar un subconjunto de valores centrales del registro sin procesar. Normalmente, estos campos básicos son los más importantes para proporcionar información de seguridad en Google Security Operations. Los valores sin asignar permanecen en el registro sin procesar, pero no almacenados en el registro UDM.

Los clientes también pueden usar la API de transferencia. para enviar datos en formato de Modelo de datos unificado (UDM) estructurado.

Personaliza la forma en que se analizan los datos transferidos

Google Security Operations proporciona las siguientes funciones que permiten a los clientes personalizar el análisis de datos en los datos de registro originales entrantes.

  • Analizadores específicos del cliente: los clientes crean un analizador personalizado. predeterminada para un tipo de registro específico que cumpla con y los requisitos de cumplimiento. Un analizador específico del cliente reemplaza el analizador predeterminado para el LogType específico. Comunícate con Google Security Operations representante para obtener información sobre la creación de un analizador específico del cliente.
  • Extensiones del analizador: Los clientes pueden agregar instrucciones de asignación personalizadas además de la configuración predeterminada del analizador. Cada cliente puede crear su conjunto único de instrucciones de asignación personalizadas. Estas asignaciones definen cómo extraer y transformar campos adicionales de de los registros originales sin procesar a los campos UDM. Una extensión de analizador no reemplaza predeterminado o específico del cliente.

Ejemplo en el que se usa un registro del proxy web de Squid

En esta sección, se proporciona un ejemplo de registro del proxy web de Squid y se describe cómo la se asignan a un registro de UDM. Para la descripción de todos los campos en el esquema de UDM, consulta la Lista de campos del modelo de datos unificado

El ejemplo de registro del proxy web de Squid contiene valores separados por espacios. Cada registro representa un evento y almacena los siguientes datos: marca de tiempo, duración, cliente, código o estado del resultado, bytes transmitidos, método de solicitud, URL, usuario, código de jerarquía y tipo de contenido. En este ejemplo, los siguientes campos se extraídas y asignadas a un registro UDM: tiempo, cliente, estado del resultado, bytes el método de solicitud y la 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

Ejemplo del proxy web Squid

Al comparar estas estructuras, observa que solo un subconjunto de la se incluyen en el registro de UDM. Algunos campos son obligatorios y otros son opcionales. Además, solo un subconjunto de las secciones del registro de la UDM contiene datos. Si el analizador no asigna datos del registro original a la UDM no verás esa sección del registro de UDM en Google Security Operations.

Valores de registro asignados a UDM

En la sección metadata, se almacena la marca de tiempo del evento. Observa que el valor se convirtió de EPOCH a formato RFC 3339. Esta conversión es opcional. La marca de tiempo puede ser se almacenan como formato EPOCH, con procesamiento previo para separar los segundos y de milisegundos en campos separados.

El metadata.event_type el campo almacena el valor NETWORK_HTTP, que es un valor enumerado que identifica el tipo de evento. El valor de metadata.event_type determina qué campos de UDM adicionales son obligatorios y cuáles son opcionales. Los operadores product_name y Los valores vendor_name contienen descripciones del dispositivo fáciles de usar que registró el registro original.

El metadata.event_type de un registro de evento de UDM no es el mismo que log_type cuando se transfieren datos con la API de transferencia. Estos dos atributos almacenan información diferente.

La sección network contiene valores del evento de registro original. Observa que ejemplo de que el valor de estado del registro original se analizó del código/estado antes de escribirse en el registro de UDM. Solo se incluyó result_code en el registro de la UDM.

Valores de registro asignados a UDM

En la sección principal, se almacena la información del cliente del registro original. El La sección target almacena la URL completamente calificada y la dirección IP.

En la sección security_result, se almacena uno de los valores de enumeración para representar la acción que se registró en el registro original.

Este es el registro UDM con formato JSON. Ten en cuenta que solo las secciones que contienen datos. Los src, observer, intermediary, about, ni las secciones extensions.

{
        "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"
        }
}

Pasos dentro de las instrucciones del analizador

Las instrucciones de asignación de datos dentro de un analizador siguen un patrón común, como sigue:

  1. Analizar y extraer datos del registro original
  2. Manipular los datos extraídos Esto incluye usar la lógica condicional para analizar valores de forma selectiva, convertir tipos de datos, reemplazar subcadenas valor, convertir a mayúsculas o minúsculas, etcétera.
  3. Asignar valores a los campos de la AUA
  4. Envía el registro de UDM asignado a la clave @output.

Analiza y extrae datos del registro original

Cómo establecer la sentencia de filtro

La sentencia filter es la primera declaración del conjunto de instrucciones de análisis. Todas las instrucciones de análisis adicionales se encuentran en la sentencia filter.

filter {

}

Inicializa variables que almacenarán los valores extraídos

Dentro de la sentencia filter, inicializa las variables intermedias que usará el analizador para almacenar los valores extraídos del registro.

Estas variables se usan cada vez que se analiza un registro individual. El valor en cada variable intermedia se establecerá en uno o más campos UDM más adelante en el las instrucciones de análisis.

  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" => ""
    }
  }

Extrae valores individuales del registro

Google Security Operations proporciona un conjunto de filtros, basado en Logstash, para extraer campos a partir de archivos de registro originales. Según el formato del registro, puedes usar uno o varios filtros de extracción para extraer todos los datos del registro. Si la cadena es:

  • JSON nativo, la sintaxis del analizador es similar a Filtro JSON que admite registros con formato JSON. No se admite el JSON anidado.
  • XML, la sintaxis del analizador es similar a la Filtro XML que admite registros con formato XML.
  • pares clave-valor, la sintaxis del analizador es similar a Filtro Kv que admite mensajes con formato de par clave-valor.
  • El formato CSV, la sintaxis del analizador es similar al filtro CSV, que admite mensajes con formato CSV.
  • todos los demás formatos, la sintaxis del analizador es similar a Filtro GROK con patrones integrados GROK . Se usan instrucciones de extracción de estilo regex.

Google Security Operations proporciona un subconjunto de las funciones disponibles en cada filtro. Google Security Operations también proporciona una sintaxis de asignación de datos personalizada que no está disponible en los filtros. Consulta la Referencia de sintaxis del analizador. para obtener una descripción de las funciones compatibles y personalizadas.

Continuando con el ejemplo de registro del proxy web de Squid, la siguiente extracción de datos incluye una combinación de sintaxis de Logstash Grok y con expresiones regulares.

La siguiente instrucción de extracción almacena valores en el siguiente intermedio variables:

  • when
  • srcip
  • action
  • returnCode
  • size
  • method
  • username
  • url
  • tgtip

Esta sentencia de ejemplo también usa la palabra clave overwrite para almacenar los valores extraídos en cada variable. Si el proceso de extracción muestra un error, on_error Establece el not_valid_log en 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"
}

Manipula y transforma los valores extraídos

Google Security Operations aprovecha las capacidades del complemento de filtro mutate de Logstash para permitir la manipulación de los valores extraídos del registro original. Google Security Operations proporciona un subconjunto de las funciones disponibles del complemento. Consulta la sintaxis del analizador para obtener una descripción de las funciones compatibles y personalizadas, como las siguientes:

  • convertir valores en un tipo de datos diferente
  • reemplazar valores en la cadena
  • Combinar dos arrays o agregar una cadena a un array Los valores de las cadenas son en un array antes de combinarlos.
  • convertir a minúsculas o mayúsculas

En esta sección, se proporcionan ejemplos de transformación de datos que se basan en el registro del proxy web de Squid. presentada anteriormente.

Cómo transformar la marca de tiempo del evento

Todos los eventos almacenados como un registro de la AUA deben tener una marca de tiempo. En este ejemplo, verifica si un valor de los datos se extrajo del registro. Luego, usa la función de fecha de Grok para hacer coincidir el valor con el formato de hora UNIX.

if [when] != "" {
  date {
    match => [
      "when", "UNIX"
    ]
   }
 }

Transforma el valor username

La siguiente sentencia de ejemplo convierte el valor de la variable username a minúsculas.

mutate {
   lowercase => [ "username"]
   }

Transforma el valor action

En el siguiente ejemplo, se evalúa el valor de la variable intermedia action y cambia el valor a ALLOW, BLOCK o UNKNOWN_ACTION, que se valores válidos para el campo UDM security_result.action. La UDM security_result.action es un tipo enumerado que almacena solo valores específicos.

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" }
      }
   }

Transforma la dirección IP de destino

En el siguiente ejemplo, se verifica un valor en la variable intermedia tgtip. Si se encuentra, el valor coincide con un patrón de dirección IP usando un Grok predefinido . Si se produce un error que coincide el valor con un patrón de dirección IP, el La función on_error establece la propiedad not_valid_tgtip en True. Si la coincidencia se realiza correctamente, no se establece la propiedad not_valid_tgtip.

if [tgtip] not in [ "","-" ] {
   grok {
     match => {
       "tgtip" => [ "%{IP:tgtip}" ]
     }
     overwrite => ["tgtip"]
     on_error => "not_valid_tgtip"
   }

Cambia el tipo de datos de returnCode y size

En el siguiente ejemplo, se convierte el valor de la variable size en uinteger y el valor de la variable returnCode en integer. Este es obligatorio porque la variable size se guardará en el Campo de UDM network.received_bytes que almacena un tipo de datos int64 El La variable returnCode se guardará en el campo de UDM network.http.response_code que almacena un tipo de datos int32.

mutate {
  convert => {
    "returnCode" => "integer"
    "size" => "uinteger"
  }
}

Asigna valores a los campos de UDM en un evento

Después de extraer los valores y procesarlos previamente, asígnalos a los campos en una UDM registro de eventos. Puedes asignar valores extraídos y estáticos a un campo de UDM.

Si propagas event.disambiguation_key, asegúrate de que este campo sea único para cada evento que se genera para un registro determinado. Si dos eventos diferentes tienen mismo disambiguation_key, se generará un comportamiento inesperado en el en un sistema de archivos.

Los ejemplos de analizador de esta sección se basan en el ejemplo de registro de proxy web de Squid que se muestra más arriba.

Guarda la marca de tiempo del evento

Cada registro de evento de la AUA debe tener un valor establecido para el campo metadata.event_timestamp de la AUA. En el siguiente ejemplo, se guarda la marca de tiempo del evento extraída del registro en la variable integrada @timestamp. Google Security Operations la guarda Es el campo de UDM metadata.event_timestamp de forma predeterminada.

mutate {
  rename => {
    "when" => "timestamp"
  }
}

Configura el tipo de evento

Cada registro de evento de UDM debe tener un valor establecido para la UDM metadata.event_type . Este campo es un tipo enumerado. El valor de este campo determina qué campos de UDM adicionales se deben propagar para que se guarde el registro de UDM El proceso de análisis y normalización fallará si falla alguno de los campos obligatorios no contengan datos válidos.

replace => {
    "event.idm.read_only_udm.metadata.event_type" => "NETWORK_HTTP"
   }
}

Guarda los valores username y method con la sentencia replace

Los valores en los campos intermedios username y method son cadenas. En el siguiente ejemplo, se verifica si existe un valor válido y, si es así, se almacena el valor username en el campo de UDM principal.user.userid y el valor method en el campo de 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}"
    }
  }
}

Guarda el action en el campo de UDM security_result.action

En la sección anterior, el valor de la variable intermedia action era Se evaluó y transformó en uno de los valores estándar del campo UDM security_result.action.

Tanto los campos de la UDM security_result como los de action almacenan un array de elementos, lo que significa que debes seguir un enfoque ligeramente diferente cuando guardes este valor.

Primero, guarda el valor transformado en un security_result.action intermediario. . El campo security_result es superior al campo action.

mutate {
   merge => {
     "security_result.action" => "action"
   }
}

A continuación, guarda el campo intermediario security_result.action intermedio en Campo de UDM security_result. El campo UDM security_result almacena un array de items, por lo que el valor se agrega a este campo.

# save the security_result field
mutate {
  merge => {
    "event.idm.read_only_udm.security_result" => "security_result"
  }
}

Almacena la dirección IP de destino y la de origen con la sentencia merge

Almacena los siguientes valores en el registro de eventos de UDM:

  • Valor de la variable intermedia de srcip para el campo de UDM principal.ip.
  • Valor de la variable intermedia de tgtip para el campo de UDM target.ip.

Los campos UDM principal.ip y target.ip almacenan un array de elementos, por lo que se agregan a cada campo.

En los siguientes ejemplos, se muestran diferentes enfoques para guardar estos valores. Durante el paso de transformación, la variable intermedia tgtip se hizo coincidir con una dirección IP mediante un patrón de Grok predefinido. En la siguiente sentencia de ejemplo, se comprueba si la propiedad not_valid_tgtip es verdadera, lo que indica que el valor tgtip no pudo coincidir con un patrón de dirección IP. Si es falsa, guarda El valor de tgtip al campo de UDM target.ip

if ![not_valid_tgtip] {
  mutate {
    merge => {
      "event.idm.read_only_udm.target.ip" => "tgtip"
    }
  }
 }

No se transformó la variable intermedia srcip. La siguiente declaración verifica si un valor se extrajo del registro original y, si lo era, guarda el valor al campo de UDM principal.ip

if [srcip] != "" {
  mutate {
    merge => {
      "event.idm.read_only_udm.principal.ip" => "srcip"
    }
  }
}

Guarda url, returnCode y size con la sentencia rename

La siguiente declaración de ejemplo almacena los siguientes valores con la declaración rename.

  • La variable url se guardó en el campo de UDM target.url.
  • La variable intermedia returnCode se guardó en el campo de UDM network.http.response_code.
  • La variable intermedia size se guardó en el campo de 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"
  }
}

Vincula el registro de UDM a la salida

La instrucción final en la instrucción de asignación de datos genera los datos procesados en un registro de evento de UDM.

mutate {
    merge => {
      "@output" => "event"
    }
  }

El código completo del analizador

Este es el ejemplo completo del código del analizador. El orden de las instrucciones no sigue el en el mismo orden que las secciones anteriores de este documento, pero obtendrás el mismo resultado.

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