Como Rastrear Eventos de Segurança Importantes do Windows com PowerShell


Muitas organizações dependem das tecnologias da Microsoft para realizar o trabalho. Ao mesmo tempo, os atores de ameaças podem explorar sistemas operacionais como o Windows. Felizmente, o Windows registra eventos de segurança do sistema operacional para ajudá-lo a rastrear esse comportamento.

Os eventos de segurança produzidos pelo Windows servem como um recurso crítico no processo de resposta a incidentes. Ferramentas como o Visualizador de Eventos do Windows da Microsoft fornecem o acesso necessário para revisar eventos capturados, mas detectar anormalidades rolando manualmente por um log lotado é irrealista.

Neste post, você aprenderá como rastrear possíveis violações de segurança no Windows, aprendendo sobre políticas de auditoria, logs de eventos do Windows e analisando eventos de segurança com o PowerShell.

Pré-requisitos

Este artigo destina-se a transmitir informações que ensinam como analisar eventos de segurança do Windows com o PowerShell. Se você deseja acompanhar alguma das demonstrações, precisará de:

  • A Windows 10+ PC – This PC will be used to generate and track down potential security events in the event log. This tutorial will be using Windows PowerShell 5.1.
  • Direitos de administrador no PC com Windows
  • A PowerShell code editor such PowerShell ISE or Visual Studio (VS) Code.

Onde o Windows Armazena Eventos de Segurança

Quando uma ação é realizada em um sistema operacional Windows, o Windows registra a ação como um evento em um ou mais logs de eventos. Os logs de eventos do Windows são armazenados no sistema de arquivos, por padrão, no diretório `%SystemRoot%\system32\winevt\logs`. Esta localização pode ser alterada modificando a subchave do registro EventLog do log de eventos correspondente.

Se você gostaria de ver onde os logs de eventos mais proeminentes (Aplicativo, Segurança e Sistema) estão armazenados em seu sistema, copie e cole o código abaixo em um console do PowerShell ou salve-o como um script.

Para acessar a localização de armazenamento do arquivo de log de Segurança, você precisa executar o código como Administrador.

#Apresentar logs de aplicativos, segurança e sistema em um array.
 $arrLogs = @(
     "Application"
     "Security"
     "System"
 )
 #Usar o cmdlet ForEach-Object para direcionar cada log respectivo com o cmdlet Get-ItemProperty.
 $arrLogs | ForEach-Object {
     #Usar o cmdlet Get-ItemProperty para listar o caminho do arquivo configurado para o log de aplicativo, segurança e sistema.
     Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\$_ -Name File | Select-Object PSChildName,File
 }

A seguinte captura de tela mostra a saída esperada do código, exibindo o nome do log e a localização de armazenamento para os arquivos de log de Aplicativo, Segurança e Sistema.

Application, Security, and System audit log location

Políticas de Auditoria: Definindo Eventos para Registrar

Por padrão, o Windows não captura todos os eventos de segurança que podem ser necessários para detectar ou investigar uma violação. Para controlar o que o Windows registra ou não, você deve definir e aplicar políticas de auditoria. Uma política de auditoria é um conjunto de instruções passadas para o Windows que informa quais eventos registrar.

Existem várias maneiras de atribuir e trabalhar com políticas de auditoria, como o uso do Group Policy. O Group Policy funciona bem se você precisar implementar políticas de auditoria em muitas máquinas. Mas neste artigo, você vai se concentrar em um único dispositivo, então usará a ferramenta auditpol. A ferramenta auditpol vem instalada com o Windows e permite que você encontre e defina políticas de auditoria em um sistema Windows.

Encontrando Políticas de Auditoria

Por exemplo, para verificar o status de todas as políticas de auditoria em seu sistema Windows, use o parâmetro /get conforme mostrado abaixo. O uso do parâmetro /category seguido por um curinga indica ao auditpol para verificar o status de todas as políticas de auditoria, não apenas uma correspondente a uma categoria ou subcategoria específica.

#Obter a configuração da política de auditoria do sistema.
auditpol /get /category:*

A seguinte captura de tela mostra uma versão truncada da saída esperada do código, exibindo a categoria de política de auditoria de Gerenciamento de Conta, subcategorias e status (Configuração).

Audit policy category, subcategory, and configuration

A Setting that is configured as No Auditing means that all events associated with that audit policy subcategory will not be logged.

Configurando Políticas de Auditoria

A ferramenta auditpol pode fazer mais do que visualizar as configurações da política de auditoria. Ela também pode modificá-las usando o comando auditpol /set. Para demonstrar futuras seções neste tutorial, abra um console do PowerShell como administrador e execute o comando abaixo. Este comando inicia o registro de todos os eventos (sucesso e falha) que fazem parte da subcategoria de Logon.

Configurar a subcategoria de Logon obriga o sistema a registrar eventos:

#Defina eventos de logon para capturar atividade de sucesso/falha.
auditpol /set /subcategory:"Logon" /success:enable /failure:enable

Existem numerosos recursos disponíveis para ajudá-lo com a melhor configuração da política de auditoria, incluindo os Benchmarks do Center for Internet Security (CIS), e os Guias de Implementação Técnica de Segurança (STIG) da Agência de Sistemas de Informação de Defesa (DISA), e orientações publicadas pela Microsoft.

Gerando Logs de Falha de Logon para Análise

Este artigo será um tutorial e esperará que você siga junto. Se você configurou o Windows para auditar eventos de logon acima, vamos agora gerar alguns eventos de segurança para análise posterior. Mais especificamente, vamos gerar 35 tentativas de logon falhas que serão registradas no log de segurança do seu sistema para simular atividade de força bruta.

1. Abra seu editor de código favorito.

2. Copie o código a seguir e cole-o no editor de código. Este trecho de código tenta abrir o processo PowerShell.exe usando o cmdlet Start-Process com nomes de usuário e senhas fictícios.

#Defina 5 nomes de usuário para registrar como falhas de logon.
 $arrUsers = @(
     "AtaBlogUser1"
     "AtaBlogUser2"
     "AtaBlogUser3"
     "AtaBlogUser4"
     "AtaBlogUser5"
 )
 #Percorra os nomes de usuário usando ForEach-Object para gerar uma falha de logon para cada um.
 $arrUsers | ForEach-Object {
     $securePassword = ConvertTo-SecureString "AtA810GRu13Z%%" -AsPlainText -Force 
     $storedCredential = New-Object System.Management.Automation.PSCredential($_, $securePassword)
     Start-Process -FilePath PowerShell -Credential $storedCredential
 }
 #Gere 30 falhas de logon para o usuário AtaBlogUser.
 $i = 0
 Do {
     $securePassword = ConvertTo-SecureString "AtA810GRu13Z%%" -AsPlainText -Force 
     $storedCredential = New-Object System.Management.Automation.PSCredential("AtaBlogUser", $securePassword)
     Start-Process -FilePath PowerShell -Credential $storedCredential
     $i++
 } Until ($i -eq 30)

3. Salve o script do PowerShell como Invoke-BogusEvents.ps1 ou qualquer nome que você preferir e execute o script.

Ao ser executado, você notará um erro esperado repetido 35 vezes indicando O nome de usuário ou senha está incorreto.

Authentication failure due to incorrect user name or password.

Se você não estiver recebendo a saída esperada, certifique-se de que o serviço de Logon Secundário esteja em estado de execução.

Acessando Eventos do Windows com PowerShell

Agora que você tem pelo menos 35 eventos de segurança do Windows, vamos explorar como encontrá-los com o cmdlet Get-WinEvent do PowerShell.

Você pode estar familiarizado com o cmdlet Get-EventLog do PowerShell, que também é usado para acessar o log de eventos programaticamente. Get-EventLog usa uma Interface de Programação de Aplicações (API) Win32 que está obsoleta e não será discutida neste post.

Abra um console do PowerShell como administrador e invoque o cmdlet Get-WinEvent, passando os parâmetros FilterHashtable e MaxEvents conforme mostrado abaixo.

O comando abaixo consulta o log de segurança do seu sistema (LogName='Security') para o evento ID 4625 (ID=4625) e retorna as 10 instâncias mais recentes (MaxEvents 10).

# Filtra o log de segurança para as primeiras 10 instâncias do Evento ID 4625
Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 10

Se bem-sucedido, você deverá ver uma saída semelhante à seguinte:

10 instances of Event ID 4625

Acessando Propriedades do Evento com Get-WinEvent

Na seção acima, você usou o Get-WinEvent para visualizar eventos de segurança do Windows em um nível mais alto, mas um evento do Windows contém muito mais informações. Cada evento do Windows possui propriedades valiosas que você pode usar para uma análise mais profunda.

Eventos do Windows como XML

Quando o Windows registra um evento, ele é armazenado em formato XML. Se esse for o caso, por que seu comando Get-WinEvent retornou objetos típicos do PowerShell? O cmdlet Get-WinEvent lê a API nativa do Windows e traduz os eventos em objetos do PowerShell para aumentar a funcionalidade.

Cada evento do Windows possui vários atributos que seguem um esquema XML ou estrutura específica.

Você verá abaixo que cada evento segue uma estrutura específica com três atributos:

  • name – Nome da propriedade
  • inType – Definição do tipo de entrada ou como o evento aceita um valor
  • outputType – Definição do tipo de saída ou como o evento é registrado

Encontrando Modelos XML de Eventos com PowerShell

Como mencionado anteriormente, cada evento de segurança do Windows é armazenado em XML e possui um esquema específico, mas como esse esquema se parece? Vamos descobrir.

Em uma das seções anteriores, você gerou alguns eventos com o ID 4625 no log de eventos de segurança. Esse tipo de evento possui atributos específicos que se aplicam apenas a ele. Para encontrar esses atributos e como o modelo se parece:

1. Abra um console do PowerShell como administrador, se ainda não estiver aberto.

2. Execute Get-WinEvent novamente, mas desta vez use o parâmetro ListProvider especificando o provedor que o Windows usa para registrar eventos no log de eventos de segurança e retorne apenas a propriedade Events.

A propriedade Events contém todos os eventos que o provedor de lista registrou e expõe o modelo XML para cada um desses eventos.

(Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events
Get Win Event List Provider

3. Agora que você tem o código para encontrar modelos para todos os tipos de eventos, restrinja isso retornando apenas o evento associado ao ID 4625.

(Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events | Where-Object -Property ID -eq 4625

4. Uma vez que você está retornando apenas o tipo de evento de Logon com o ID do evento 4625, limite-se a mostrar apenas a propriedade Template como abaixo.

#Obter modelo XML de evento para propriedades do evento com ID 4625.
 ((Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events | Where-Object -Property ID -eq 4625).Template

A seguinte captura de tela mostra uma versão truncada da saída do código, identificando o nome da propriedade do evento, o tipo de entrada e o tipo de saída. Você pode ver que o ID do evento 4625 possui propriedades do evento com várias definições de entrada e saída.

A captura de tela abaixo destaca a propriedade SubjectUserSid do ID do evento 4625. Este evento em particular aceita um tipo de entrada (inType) de win:SID e renderiza a saída (outType) como uma string, que é como é armazenada no log de segurança.

XML template example

Como o PowerShell Traduz XML em Objetos

Agora que você viu como o Windows armazena eventos em XML e como ver esses modelos no PowerShell, vamos ver como o PowerShell traduz esse XML em objetos.

1. Execute o comando Get-WinEvent novamente para retornar nosso ID de evento 4625. Até agora, nada de novo. Observe que o PowerShell só mostra quatro propriedades, TimeCreated, Id, LevelDisplayName e Message.

Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1
Get-WinEvent FilterHashtable

Por padrão, o cmdlet Get-WinEvent não retorna todos os atributos da fonte de dados XML do evento como um objeto PowerShell.

2. Agora, encaminhe a saída do comando acima para o cmdlet Select-Object e especifique o parâmetro Property passando um valor para mostrar todas as propriedades.

Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1 | Select-Object -Property *

Observe abaixo que o PowerShell estava ocultando muitas propriedades diferentes. Mais especificamente, uma propriedade chamada Properties. A propriedade Properties contém o valor de cada atributo do evento que você viu anteriormente no modelo XML.

Powershell hiding Properties

3. Limite a saída do comando Get-WinEvent acima para expor a propriedade Properties. Esta propriedade armazena todas as propriedades do evento, não as propriedades do objeto PowerShell, em um array.

# Saída do array de propriedades do evento para a primeira instância do ID do Evento 4625
 $eventProperties = (Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1).properties
 $eventProperties

No lado esquerdo da captura de tela abaixo está a saída do comando acima. O array contém os valores para cada um dos atributos XML no modelo XML no lado direito da captura de tela.

A saída do código mostrada na captura de tela comunica que ocorreu uma falha de autenticação para o usuário AtaBlogUser (TargetUserName) do sistema Desktop-XXXXX (WorkstationName) usando um Endereço IP de ::1 (IpAddress).

Expected output correlating property values to Event ID 4625’s XML template.

Talvez você queira retornar apenas o valor para a propriedade de evento TargetUserName. Como você já armazenou todas as propriedades do evento em uma variável chamada $eventProperties, faça referência ao quinto índice, que contém o valor para TargetUserName.

Você deve fazer referência à propriedade value no objeto de propriedade de evento individual para retornar apenas o valor (AtaBlogUser). $eventProperties[5].value

$eventProperties[5].value
Event attribute property positions

As práticas descritas ao longo desta seção serão usadas em seções subsequentes para rastrear a tentativa de força bruta que você simulou anteriormente neste post.

Detectando um Ataque de Força Bruta

Você está agora preparado para usar suas habilidades no PowerShell para rastrear o ataque de força bruta que você replicou anteriormente neste post! Vamos colocar suas habilidades à prova simulando como seria rastrear um ataque de força bruta com base em um intervalo de tempo específico.

Digamos que você foi alertado para um incidente em que sua organização acredita que alguém está tentando usar uma conta administrativa para fazer login em um servidor Windows importante. Essa atividade começou ontem. Você precisa descobrir o número do evento ID 4625: Falha ao fazer login em uma conta que ocorreu nas últimas 24 horas e determinar o tipo de logon de cada evento.

1. Encontre todos os eventos com o ID 4625 (ID=4625) no log de segurança do Windows (LogName="Security") das últimas 24 horas (StartTime=((Get-Date).AddDays(-1).Date), terminando no momento atual (Get-Date).

$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1));EndTime=(Get-Date)}

2. Agora, conte todos os eventos armazenados na variável para determinar se há mais eventos de falha de logon do que o esperado.

$events.Count

Agora você deverá ver um valor numérico indicando quantas vezes o evento ID 4625 foi encontrado no log de eventos de segurança nas últimas 24 horas.

3. Então, você determinou que ocorreu um ataque de força bruta, agora rastreie mais informações sobre esses eventos de segurança do Windows. Para fazer isso, retorne apenas os atributos de cada um dos eventos que você está interessado.

Como mencionado anteriormente, cada valor para um evento específico é armazenado em uma matriz com um índice específico. As propriedades de evento interessantes para esta demonstração estão abaixo.

  • TargetUserName Índice: [5]
  • LogonType Índice: [10]
  • WorkstationName Índice: [13]
  • IpAddress Índice: [19]

O exemplo de código abaixo lê cada objeto na variável $events, reúne apenas as propriedades interessantes e as concatena em uma única linha.

#Extrair as propriedades do evento TargetUserName, LogonType, WorkstationName e IpAddress de todas as instâncias do Evento ID 4625 nas últimas 24 horas.
 $events | ForEach-Object {
     ## Referenciar a propriedade do objeto properties
     ## Retornar apenas o valor dos índices 5, 10, 13 e 19 da matriz de propriedades
     ## Concatenar todos os valores juntos, unindo-os com uma vírgula
     $_.properties[5,10,13,19].value -join ", "
 }

A captura de tela a seguir mostra uma versão truncada da saída esperada do código, detalhando uma lista separada por vírgulas de TargetUserName, LogonType, WorkstationName e IpAddress.

A truncated version of the code’s output, detailing TargetUserName, LogonType, WorkstationName, and IpAddress property values.

4. Como você viu no modelo XML anterior, o modelo do evento ID 4625 possui um atributo LogonType. Este atributo indica o método pelo qual a conta tentou autenticar. Através de uma investigação adicional, você notou que o LogonType era diferente ocasionalmente.

LogonType attribute

O valor LogonType é um valor numérico de 2 a 11, mas o que isso significa? Você realiza algumas pesquisas e descobre o significado de cada valor.

2 – Interativo – Um usuário fez login neste computador.

3 – Rede – Um usuário ou computador fez login neste computador a partir da rede.

4 – Lote – O tipo de logon em lote é usado por servidores em lote, onde processos podem ser executados em nome de um usuário sem sua intervenção direta.

5 – Serviço – Um serviço foi iniciado pelo Gerenciador de Controle de Serviço.

7 – Desbloquear – Esta estação de trabalho foi desbloqueada.

8 – Rede em Texto Puro – Um usuário fez login neste computador a partir da rede. A senha do usuário foi enviada para o pacote de autenticação em sua forma não-hashed. Os pacotes de autenticação integrados sempre fazem o hash das credenciais antes de enviá-las pela rede. As credenciais não são transmitidas pela rede em texto puro (também chamado de texto simples).

9 – Novas Credenciais – Um chamador clonou seu token atual e especificou novas credenciais para conexões de saída. A nova sessão de logon tem a mesma identidade local, mas usa credenciais diferentes para outras conexões de rede.

10 – Interativo Remoto – Um chamador clonou seu token atual e especificou novas credenciais para conexões de saída. A nova sessão de logon tem a mesma identidade local, mas usa credenciais diferentes para outras conexões de rede.

11 – Interativo Armazenado em Cache – Um usuário fez login neste computador com credenciais de rede armazenadas localmente no computador. O controlador de domínio não foi contatado para verificar as credenciais.

Agora que você tem uma boa compreensão de cada LogonType, em vez de ver um valor numérico na saída, você deseja uma string mais descritiva. Para criar “mapas” no PowerShell, use uma hashtable.

$logonTypes = @{
     [uint32]2 = "Interactive"
     [uint32]3 = "Network"
     [uint32]4 = "Batch"
     [uint32]5 = "Service"
     [uint32]7 = "Unlock"
     [uint32]8 = "NetworkCleartext"
     [uint32]9 = "NewCredentials"
     [uint32]10 = "RemoteInteractive"
     [uint32]11 = "CachedInteractive"
 }

5. Combine Get-WinEvent e a hashtable LogonType com ForEach-Object para criar um script que retornará apenas as propriedades que você deseja com um valor LogonType amigável ao usuário, como mostrado abaixo. O cmdlet Format-Table adiciona à saída amigável ao usuário, formatando a resposta do PowerShell como uma tabela.

# Use o Get-WinEvent para acessar as propriedades de cada instância registrada do Evento ID 4625
$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
## Crie o "mapa" do valor numérico para string
$logonTypes = @{
    [uint32]2 = "Interactive"
    [uint32]3 = "Network"
    [uint32]4 = "Batch"
    [uint32]5 = "Service"
    [uint32]7 = "Unlock"
    [uint32]8 = "NetworkCleartext"
    [uint32]9 = "NewCredentials"
    [uint32]10 = "RemoteInteractive"
    [uint32]11 = "CachedInteractive"
}
## Comece a processar cada objeto na matriz $events
$events | ForEach-Object {
    ## Procure o valor numérico na hashtable
    $logonType = $logonTypes[$_.properties[10].value] 
    # Crie um objeto PowerShell personalizado para exibir as propriedades do evento relevantes
    [PSCustomObject]@{     
        TimeCreated = $_.TimeCreated     
        TargetUserName = $_.properties[5].value     
        LogonType = $logonType     
        WorkstationName = $_.properties[13].value     
        IpAddress = $_.properties[19].value 
    }
} | Format-Table -Wrap

Neste ponto, você agora tem um script que retorna objetos do tipo PSCustomObject permitindo que você realize muitos tipos diferentes de análises! Para finalizar a análise deste tutorial, priorize as tentativas de falha de autenticação por TargetUserName. Para priorizar as falhas pela propriedade TargetUserName, combine o código acima com o cmdlet Group-Object. Use Sort-Object e seu parâmetro Descending para identificar o usuário mais ofensivo.

#Use Get-WinEvent para acessar as propriedades de cada instância registrada do Evento ID 4625
$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
## Criar o valor numérico para string "mapa"
$logonTypes = @{
    [uint32]2 = "Interactive"
    [uint32]3 = "Network"
    [uint32]4 = "Batch"
    [uint32]5 = "Service"
    [uint32]7 = "Unlock"
    [uint32]8 = "NetworkCleartext"
    [uint32]9 = "NewCredentials"
    [uint32]10 = "RemoteInteractive"
    [uint32]11 = "CachedInteractive"
}
## Iniciar o processamento de cada objeto no array $eventos
$events | ForEach-Object {
    ## Procurar o valor numérico na tabela de hash
    $logonType = $logonTypes[$_.properties[10].value] 
    #Criar objeto PowerShell personalizado para exibir propriedades relevantes do evento
    [PSCustomObject]@{     
        TimeCreated = $_.TimeCreated     
        TargetUserName = $_.properties[5].value     
        LogonType = $logonType     
        WorkstationName = $_.properties[13].value     
        IpAddress = $_.properties[19].value 
    }
} | Group-Object -Property TargetUserName | Sort-Object -Property Count -Descending

Ótimo trabalho! Você acabou de usar o PowerShell para detectar a tentativa de força bruta que simulou anteriormente neste post. De acordo com a saída, AtaBlogUser falhou ao autenticar 30 vezes nas últimas 24 horas!

AtaBlogUser Logon Failures

Próximos Passos

Neste tutorial, você aprendeu como o Windows registra eventos, como habilitar o registro de eventos para determinados tipos de evento e como construir uma ferramenta do PowerShell para consultar esses eventos.

Com o script do PowerShell que você tem agora, como você pode melhorá-lo? Como você usará o código que aprendeu hoje para construir uma ferramenta melhor?

Source:
https://adamtheautomator.com/windows-security-events/