Criar um analisador ASIM

Concluído

Os usuários do ASIM (Advanced Security Information Model) usam analisadores unificadores em vez de nomes de tabelas em suas consultas, para exibir dados em um formato normalizado e incluir todos os dados relevantes para o esquema na consulta. Os analisadores unificadores, por sua vez, usam analisadores específicos da fonte para lidar com os detalhes específicos de cada fonte.

O Microsoft Sentinel fornece analisadores internos específicos da fonte para muitas fontes de dados. Você pode querer modificar ou desenvolver esses analisadores específicos da fonte nas seguintes situações:

Quando seu dispositivo fornece eventos que se ajustam a um esquema ASIM, mas um analisador específico de origem para seu dispositivo e o esquema relevante não está disponível no Microsoft Sentinel.

Quando analisadores específicos de origem ASIM estão disponíveis para seu dispositivo, mas seu dispositivo envia eventos em um método ou um formato diferente do esperado pelos analisadores ASIM. Por exemplo:

Seu dispositivo de origem pode ser configurado para enviar eventos de forma não padrão.

Seu dispositivo pode ter uma versão diferente da suportada pelo analisador ASIM.

Os eventos podem ser coletados, modificados e encaminhados por um sistema intermediário.

Processo de desenvolvimento do analisador personalizado

O fluxo de trabalho a seguir descreve as etapas de alto nível no desenvolvimento de um analisador ASIM, específico da origem:

  1. Colete logs de amostras.

  2. Identifique os esquemas ou esquemas que os eventos enviados da origem representam.

  3. Mapeie os campos de evento de origem para o(s) esquema(s) identificado(s).

  4. Desenvolva um ou mais analisadores ASIM para sua fonte. Você precisará desenvolver um analisador de filtragem e um analisador sem parâmetros para cada esquema relevante para a origem.

  5. Teste o analisador.

  6. Implante os analisadores em seus espaços de trabalho do Microsoft Sentinel.

  7. Atualize o analisador unificador ASIM relevante para fazer referência ao novo analisador personalizado.

  8. Você também pode querer contribuir com seus analisadores para a distribuição ASIM primária. Os analisadores contribuídos também podem ser disponibilizados em todos os espaços de trabalho como analisadores integrados.

Coletar logs de amostra

Para criar analisadores ASIM eficazes, você precisa de um conjunto representativo de logs, o que, na maioria dos casos, exigirá a configuração do sistema de origem e conectá-lo ao Microsoft Sentinel. Se não tiver o dispositivo de origem disponível, os serviços pré-pagos na nuvem permitem-lhe implementar muitos dispositivos para desenvolvimento e teste.

Além disso, encontrar a documentação do fornecedor e amostras para os logs pode ajudar a acelerar o desenvolvimento e reduzir erros, garantindo uma ampla cobertura do formato de log.

Um conjunto representativo de logs deve incluir:

  • Eventos com diferentes resultados de eventos.
  • Eventos com diferentes ações de resposta.
  • Diferentes formatos para nome de usuário, nome de host e IDs e outros campos que exigem normalização de valor.

Mapeamento

Antes de desenvolver um analisador, mapeie as informações disponíveis no evento ou eventos de origem para o esquema identificado:

  • Mapeie todos os campos obrigatórios e, de preferência, também os campos recomendados.
  • Tente mapear qualquer informação disponível da fonte para campos normalizados. Se não estiver disponível como parte do esquema selecionado, considere o mapeamento para campos disponíveis em outros esquemas.
  • Mapeie valores para campos na origem para os valores normalizados permitidos pelo ASIM. O valor original é armazenado em um campo separado, como EventOriginalResultDetails.

Desenvolvimento de analisadores

Desenvolva uma filtragem e um analisador sem parâmetros para cada esquema relevante.

Um analisador personalizado é uma consulta KQL desenvolvida na página Microsoft Sentinel Logs. A consulta do analisador tem três partes:

Filtrar > Analisar > campos Preparar

Filtrar os registos relevantes

Em muitos casos, uma tabela no Microsoft Sentinel inclui vários tipos de eventos. Por exemplo:

  • A tabela Syslog tem dados de várias fontes.
  • As tabelas personalizadas podem incluir informações de uma única fonte que fornece mais de um tipo de evento e pode se ajustar a vários esquemas.

Portanto, um analisador deve primeiro filtrar apenas os registros relevantes para o esquema de destino.

A filtragem no KQL é feita usando o operador where . Por exemplo, o evento 1 do Sysmon relata a criação do processo e, portanto, é normalizado para o esquema ProcessEvent. O evento Sysmon evento 1 faz parte da tabela Evento , portanto, você deve usar o seguinte filtro:

Event | where Source == "Microsoft-Windows-Sysmon" and EventID == 1

Importante

Um analisador não deve filtrar por tempo. A consulta que usa o analisador aplicará um intervalo de tempo.

Filtrando por tipo de fonte usando uma Lista de observação

Em alguns casos, o evento em si não contém informações que permitam filtrar tipos de fonte específicos.

Por exemplo, os eventos DNS do Infoblox são enviados como mensagens Syslog e são difíceis de distinguir das mensagens Syslog enviadas de outras fontes. Nesses casos, o analisador se baseia em uma lista de fontes que define os eventos relevantes. Esta lista é mantida na lista de observação ASimSourceType.

Para usar a lista de observação ASimSourceType em seus analisadores:

  • Inclua a seguinte linha no início do analisador:
let Sources_by_SourceType=(sourcetype:string){_GetWatchlist('ASimSourceType') | where SearchKey == tostring(sourcetype) | extend Source=column_ifexists('Source','') | where isnotempty(Source)| distinct Source };
  • Adicione um filtro que use a lista de observação na seção de filtragem do analisador. Por exemplo, o analisador DNS Infoblox inclui o seguinte na seção de filtragem:
| where Computer in (Sources_by_SourceType('InfobloxNIOS'))

Para usar este exemplo em seu analisador:

  • Substitua Computador pelo nome do campo que inclui as informações de origem da sua fonte. Você pode manter isso como computador para qualquer analisador baseado no Syslog.

  • Substitua o token InfobloxNIOS por um valor de sua escolha para seu analisador. Informe aos usuários do analisador que eles devem atualizar a lista de observação ASimSourceType usando o valor selecionado e a lista de fontes que enviam eventos desse tipo.

Filtragem baseada em parâmetros do analisador

Ao desenvolver analisadores de filtragem, certifique-se de que o analisador aceita os parâmetros de filtragem para o esquema relevante, conforme documentado no artigo de referência para esse esquema. Usar um analisador existente como ponto de partida garante que o analisador inclua a assinatura de função correta. Na maioria dos casos, o código de filtragem real também é semelhante para filtrar analisadores para o mesmo esquema.

Ao filtrar, certifique-se de que:

  • Filtre antes de analisar usando campos físicos. Se os resultados filtrados não forem precisos o suficiente, repita o teste após a análise para ajustar os resultados. Para obter mais informações, consulte Otimização de filtragem.
  • Não filtre se o parâmetro não estiver definido e ainda tiver o valor padrão.

Os exemplos a seguir mostram como implementar a filtragem para um parâmetro string, onde o valor padrão é geralmente '*', e para um parâmetro list, onde o valor padrão geralmente é uma lista vazia.

srcipaddr=='*' or ClientIP==srcipaddr
array_length(domain_has_any) == 0 or Name has_any (domain_has_any)

Otimização de filtragem

Para garantir o desempenho do analisador, observe as seguintes recomendações de filtragem:

  • Filtre sempre em campos internos em vez de analisados. Embora às vezes seja mais fácil filtrar usando campos analisados, isso afeta drasticamente o desempenho.
  • Use operadores que fornecem desempenho otimizado. Em particular, ==, tem, e começa. O uso de operadores como contém ou corresponde ao regex também afeta drasticamente o desempenho.

As recomendações de filtragem para o desempenho nem sempre podem ser fáceis de seguir. Por exemplo, usar tem é menos preciso do que contém. Em outros casos, a correspondência do campo interno, como SyslogMessage, é menos precisa do que comparar um campo extraído, como DvcAction. Nesses casos, recomendamos que você ainda pré-filtre usando um operador de otimização de desempenho em um campo interno e repita o filtro usando condições mais precisas após a análise.

Para obter um exemplo, consulte o seguinte trecho do analisador DNS Infoblox. O analisador primeiro verifica se o campo SyslogMessage tem a palavra cliente. No entanto, o termo pode ser usado em um lugar diferente na mensagem, portanto, depois de analisar o campo Log_Type, o analisador verifica novamente se a palavra cliente era realmente o valor do campo.

Syslog | where ProcessName == "named" and SyslogMessage has "client"
…
      | extend Log_Type = tostring(Parser[1]),
      | where Log_Type == "client"

A Analisar

Depois que a consulta seleciona os registros relevantes, pode ser necessário analisá-los. Normalmente, a análise é necessária se vários campos de evento forem transmitidos em um único campo de texto.

Os operadores KQL que executam a análise estão listados abaixo, ordenados por sua otimização de desempenho. O primeiro fornece o desempenho mais otimizado, enquanto o último fornece o desempenho menos otimizado.

Operator Description
split Analise uma cadeia de valores delimitados.
parse_csv Analise uma cadeia de valores formatada como uma linha CSV (valores separados por vírgula).
analisar Analise vários valores de uma cadeia de caracteres arbitrária usando um padrão, que pode ser um padrão simplificado com melhor desempenho ou uma expressão regular.
extract_all Analise valores únicos de uma cadeia de caracteres arbitrária usando uma expressão regular. extract_all tem um desempenho semelhante para analisar se o último usa uma expressão regular.
extrato Extraia um único valor de uma cadeia de caracteres arbitrária usando uma expressão regular. O uso de extract fornece melhor desempenho do que analisar ou extract_all se um único valor for necessário. No entanto, o uso de várias ativações de extrato sobre a mesma cadeia de origem é menos eficiente do que uma única análise ou extract_all e deve ser evitado.
parse_json Analise os valores em uma cadeia de caracteres formatada como JSON. Se apenas alguns valores forem necessários do JSON, o uso de análise, extração ou extract_all proporcionará um melhor desempenho.
parse_xml Analise os valores em uma cadeia de caracteres formatada como XML. Se apenas alguns valores forem necessários do XML, o uso de análise, extração ou extract_all proporcionará um melhor desempenho.

Além da cadeia de caracteres de análise, a fase de análise pode exigir mais processamento dos valores originais, incluindo:

  • Formatação e conversão de tipos. O campo de origem, uma vez extraído, pode precisar ser formatado para se ajustar ao campo do esquema de destino. Por exemplo, talvez seja necessário converter uma cadeia de caracteres que representa data e hora em um campo datetime. Funções como todatetime e tohex são úteis nesses casos.

  • Pesquisa de valor. O valor do campo de origem, uma vez extraído, pode precisar ser mapeado para o conjunto de valores especificado para o campo de esquema de destino. Por exemplo, algumas fontes relatam códigos de resposta DNS numéricos, enquanto o esquema exige os códigos de resposta de texto mais comuns. As funções iff e case podem ser úteis para mapear alguns valores.

    Por exemplo, o analisador DNS da Microsoft atribui o campo EventResult com base na ID do Evento e no Código de Resposta usando uma instrução iff, da seguinte maneira:

    extend EventResult = iff(EventId==257 and ResponseCode==0 ,'Success','Failure')
    

    Para vários valores, use datatable e lookup, como demonstrado no mesmo analisador DNS:

    let RCodeTable = datatable(ResponseCode:int,ResponseCodeName:string) [ 0, 'NOERROR', 1, 'FORMERR'....];
    ...
     | lookup RCodeTable on ResponseCode
     | extend EventResultDetails = case (
     isnotempty(ResponseCodeName), ResponseCodeName,
     ResponseCode between (3841 .. 4095), 'Reserved for Private Use',
     'Unassigned')
    

Mapeando valores

Em muitos casos, o valor original extraído precisa ser normalizado. Por exemplo, no ASIM um endereço MAC usa dois pontos como separador, enquanto a fonte pode enviar um endereço MAC delimitado por hífen. O operador primário para a transformação de valores é estendido, juntamente com um amplo conjunto de funções de cadeia KQL, numéricas e de data, como demonstrado na seção Análise acima.

Use instruções case, iff e lookup quando houver necessidade de mapear um conjunto de valores para os valores permitidos pelo campo de destino.

Quando cada valor de origem for mapeado para um valor de destino, defina o mapeamento usando o operador datatable e pesquise para mapear. Por exemplo

let NetworkProtocolLookup = datatable(Proto:real, NetworkProtocol:string)[
        6, 'TCP',
        17, 'UDP'
   ];
    let DnsResponseCodeLookup=datatable(DnsResponseCode:int,DnsResponseCodeName:string)[
      0,'NOERROR',
      1,'FORMERR',
      2,'SERVFAIL',
      3,'NXDOMAIN',
      ...
   ];
   ...
   | lookup DnsResponseCodeLookup on DnsResponseCode
   | lookup NetworkProtocolLookup on Proto

Observe que a pesquisa é útil e eficiente também quando o mapeamento tem apenas dois valores possíveis.

Quando as condições de mapeamento forem mais complexas, use as funções iff ou case . A função iff permite mapear dois valores:

| extend EventResult = 
      iff(EventId==257 and ResponseCode==0,'Success','Failure’)

A função case suporta mais de dois valores de destino. O exemplo abaixo mostra como combinar pesquisa e maiúsculas e minúsculas. O exemplo de pesquisa acima retorna um valor vazio no campo DnsResponseCodeName se o valor de pesquisa não for encontrado. O exemplo de caso abaixo o aumenta usando o resultado da operação de pesquisa, se disponível, e especificando condições adicionais caso contrário.

| extend DnsResponseCodeName = 
      case (
        DnsResponseCodeName != "", DnsResponseCodeName,
        DnsResponseCode between (3841 .. 4095), 'Reserved for Private Use',
        'Unassigned'
      )

Preparar campos no conjunto de resultados

O analisador deve preparar os campos no conjunto de resultados para garantir que os campos normalizados sejam usados.

Os seguintes operadores KQL são usados para preparar campos no seu conjunto de resultados:

Operator Description Quando usar em um analisador
projeto-renomear Renomeia campos. Se um campo existir no evento real e só precisar ser renomeado, use project-rename. O campo renomeado ainda se comporta como um campo embutido, e as operações no campo têm um desempenho muito melhor.
projeto-fora Remove campos. Use o projeto para campos específicos que você deseja remover do conjunto de resultados. Recomendamos não remover os campos originais que não estão normalizados do conjunto de resultados, a menos que criem confusão ou sejam muito grandes e possam ter implicações de desempenho.
projeto Seleciona campos que existiam antes ou foram criados como parte da instrução e remove todos os outros campos. Não recomendado para uso em um analisador, pois o analisador não deve remover nenhum outro campo que não esteja normalizado. Se você precisar remover campos específicos, como valores temporários usados durante a análise, use project-away para removê-los dos resultados.
estender Adicione aliases. Além de sua função na geração de campos calculados, o operador extend também é usado para criar aliases.

Manipular variantes de análise

Em muitos casos, os eventos em um fluxo de eventos incluem variantes que exigem lógica de análise diferente. Para analisar diferentes variantes em um único analisador, use instruções condicionais, como iff e case, ou use uma estrutura de união.

Para usar union para lidar com várias variantes, crie uma função separada para cada variante e use a instrução union para combinar os resultados:

let AzureFirewallNetworkRuleLogs = AzureDiagnostics
    | where Category == "AzureFirewallNetworkRule"
    | where isnotempty(msg_s);
let parseLogs = AzureFirewallNetworkRuleLogs
    | where msg_s has_any("TCP", "UDP")
    | parse-where
        msg_s with           networkProtocol:string 
        " request from "     srcIpAddr:string
        ":"                  srcPortNumber:int
    …
    | project-away msg_s;
let parseLogsWithUrls = AzureFirewallNetworkRuleLogs
    | where msg_s has_all ("Url:","ThreatIntel:")
    | parse-where
        msg_s with           networkProtocol:string 
        " request from "     srcIpAddr:string
        " to "               dstIpAddr:string
    …
union parseLogs,  parseLogsWithUrls…

Para evitar eventos duplicados e processamento excessivo, certifique-se de que cada função comece filtrando, usando campos nativos, apenas os eventos que se destina a analisar. Além disso, se necessário, use o projeto-away em cada filial, antes do sindicato.

Implantar analisadores

Implante analisadores manualmente copiando-os para a página Log do Azure Monitor e salvando a consulta como uma função. Este método é útil para testes. Para obter mais informações, consulte Criar uma função.

Para implantar um grande número de analisadores, recomendamos o uso de modelos ARM do analisador, da seguinte maneira:

  1. Crie um arquivo YAML com base no modelo relevante para cada esquema e inclua sua consulta nele. Comece com o modelo YAML relevante para o seu esquema e tipo de analisador, filtragem ou sem parâmetros.

  2. Use o conversor de modelo ASIM Yaml para ARM para converter seu arquivo YAML em um modelo ARM.

  3. Se estiver implantando uma atualização, exclua versões mais antigas das funções usando o portal ou a função excluir a ferramenta PowerShell.

  4. Implante seu modelo usando o portal do Azure ou o PowerShell.

Você também pode combinar vários modelos em um único processo de implantação usando modelos vinculados.