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 ameaçadores podem explorar sistemas operacionais como o Windows. Felizmente, o Windows registra eventos de segurança do sistema operacional para ajudar 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 os 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, conhecendo políticas de auditoria, logs de eventos do Windows e analisando eventos de segurança com o PowerShell.

Pré-requisitos

Este artigo tem o objetivo de fornecer informações que ensinem 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 é executada 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 respectivo log de eventos.

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

Para acessar o local de armazenamento do arquivo de log de Segurança, é necessário executar o código como Administrador.

#Apresentar logs de aplicação, segurança e sistema em uma matriz.
 $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 aplicação, segurança e sistema.
     Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\$_ -Name File | Select-Object PSChildName,File
 }

A captura de tela a seguir mostra a saída esperada do código, exibindo o nome do log e o local de armazenamento dos arquivos de log de Aplicação, 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 enviadas ao Windows que dizem a ele quais eventos devem ser registrados.

Existem algumas maneiras diferentes 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 já vem instalada com o Windows e permite que você encontre e defina políticas de auditoria em um sistema Windows.

Localizando Políticas de Auditoria

Por exemplo, para encontrar 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 caractere curinga diz ao auditpol para encontrar o status de todas as políticas de auditoria, não apenas aquelas que correspondem a uma categoria ou subcategoria específica.

#Obtenha 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 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 Logon.

Configurar a subcategoria Logon força o sistema a registrar eventos:

#Configure os Eventos de Logon para capturar atividades de Sucesso/Falha.
auditpol /set /subcategory:"Logon" /success:enable /failure:enable

Há numerosos recursos disponíveis para ajudá-lo com a configuração da política de auditoria de melhores práticas, 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 espera 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 falhadas 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 seguinte código e cole 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 falsos.

#Define 5 nomes de usuário para registrar como falhas de login.
 $arrUsers = @(
     "AtaBlogUser1"
     "AtaBlogUser2"
     "AtaBlogUser3"
     "AtaBlogUser4"
     "AtaBlogUser5"
 )
 #Loop através dos nomes de usuário usando ForEach-Object para gerar uma falha de login 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
 }
 #Gera 30 falhas de login 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 PowerShell como Invoke-BogusEvents.ps1 ou qualquer nome que você preferir e execute o script.

Ao executar, 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 está 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 certeza de ter pelo menos 35 eventos de segurança do Windows, vamos ver 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 Aplicativos (API) Win32 que está obsoleta e não será discutida nesta postagem.

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).

#Filtrar 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 ver eventos de segurança do Windows em um nível alto, mas um evento do Windows contém muito mais informações. Cada evento do Windows possui propriedades valiosas que você pode usar para análises mais profundas.

Eventos do Windows como XML

Quando o Windows registra um evento, ele é armazenado no formato XML. Se esse for o caso, por que seu comando Get-WinEvent retorna objetos PowerShell típicos? O cmdlet Get-WinEvent lê a API nativa do Windows e traduz os eventos em objetos 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:

  • nome – O nome da propriedade
  • inType – A definição do tipo de entrada ou como o evento aceita um valor
  • outputType – A definição do tipo de saída ou como o evento é registrado

Localizando Modelos XML de Evento com PowerShell

Como mencionado anteriormente, todo 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 tem 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 o tiver 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 Eventos.

A propriedade Eventos 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 esteja retornando apenas o tipo de evento de Logon com o ID do evento 4625, limite-o para mostrar apenas a propriedade Modelo como abaixo.

#Obter modelo XML de evento para propriedades de evento do 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 de 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 específico aceita um tipo de entrada (inType) de win:SID e renderiza a saída (outType) como uma string, que é como ela é 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 do evento 4625. Até agora, isso não é nada novo. Observe que o PowerShell mostra apenas 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 do PowerShell.

2. Agora, envie a saída do comando acima para o cmdlet Select-Object e especifique o parâmetro Property passando um valor de 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 uma matriz.

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

À esquerda da captura de tela abaixo está a saída do comando acima. A matriz contém os valores de 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 na 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 apenas retornar o valor da propriedade do 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 do 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 testar suas habilidades simulando como seria rastrear um ataque de força bruta com base em um intervalo de tempo específico.

Digamos que você tenha sido alertado sobre 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 de eventos com o ID 4625: Uma conta falhou ao fazer login que ocorreram 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") nos últimos 24 horas (StartTime=((Get-Date).AddDays(-1).Date), terminando no horário 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 com o 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 de seu interesse.

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

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

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

# Extrai as propriedades TargetUserName, LogonType, WorkstationName e IpAddress de todas as instâncias do Evento ID 4625 nas últimas 24 horas.
 $events | ForEach-Object {
     ## Referencie a propriedade do objeto de propriedades
     ## Retorne apenas o valor dos índices 5, 10, 13 e 19 da matriz de propriedades
     ## Concatene 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 visto anteriormente no modelo XML, o modelo do evento ID 4625 possui um atributo LogonType. Esse atributo indica o método pelo qual a conta tentou autenticar. Após algumas investigações adicionais, notou-se que o LogonType era ocasionalmente diferente.

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 conectado a este computador.

3 – Rede – Um usuário ou computador conectado a este computador através da rede.

4 – Lote – O tipo de logon em lote é usado por servidores de lote, onde processos podem estar sendo 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 – Desbloqueio – Esta estação de trabalho foi desbloqueada.

8 – TextoSemCriptografiaDeRede – Um usuário conectado a este computador através da rede. A senha do usuário foi passada para o pacote de autenticação em sua forma não-hashing. Os pacotes de autenticação integrados sempre criptografam credenciais antes de enviá-las pela rede. As credenciais não atravessam a rede em texto simples (também chamado de texto limpo).

9 – NovasCredenciais – 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 diferentes credenciais para outras conexões de rede.

10 – InterativoRemoto – 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 diferentes credenciais para outras conexões de rede.

11 – InterativoEmCache – Um usuário conectado a este computador com credenciais de rede que foram 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ê quer 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 só retornará 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 Get-WinEvent para acessar as propriedades de cada instância registrada do Event ID 4625
$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
## Criar 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"
}
## Iniciar o processamento de cada objeto na matriz $events
$events | ForEach-Object {
    ## Procurar o valor numérico na hashtable
    $logonType = $logonTypes[$_.properties[10].value] 
    # Criar objeto PowerShell personalizado para saída das propriedades relevantes do evento
    [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álise! 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 interruptor Descending para identificar o usuário mais ofensivo.

#Use Get-WinEvent to access the properties of each logged instance of Event ID 4625
$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
## Create the numerical value to string "map"
$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"
}
## Begin processing each object in the $events array
$events | ForEach-Object {
    ## Look up the numerical value in the hashtable
    $logonType = $logonTypes[$_.properties[10].value] 
    #Create custom PowerShell object to output relevant event properties 
    [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 na autenticação 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 eventos e como criar uma ferramenta PowerShell para consultar esses eventos.

Com o script PowerShell que você possui agora, como você pode melhorá-lo? Como você pegará o código que aprendeu hoje e construirá uma ferramenta melhor?

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