Come tracciare gli eventi importanti della sicurezza di Windows con PowerShell


Molte organizzazioni si affidano alle tecnologie Microsoft per svolgere il lavoro. Allo stesso tempo, i minacce informatiche possono sfruttare sistemi operativi come Windows. Per fortuna, Windows registra eventi di sicurezza del sistema operativo per aiutarti a individuare questo comportamento.

Gli eventi di sicurezza prodotti da Windows fungono da risorsa critica nel processo di risposta agli incidenti. Strumenti come il Visualizzatore eventi di Windows di Microsoft ti forniscono l’accesso necessario per esaminare gli eventi catturati, ma individuare anomalie scorrendo manualmente un registro affollato è irrealistico.

In questo post, imparerai come individuare potenziali violazioni della sicurezza in Windows, conoscendo le policy di audit, i log degli eventi di Windows e analizzando gli eventi di sicurezza con PowerShell.

Prerequisiti

Questo articolo mira a fornire informazioni che ti insegnano come analizzare gli eventi di sicurezza di Windows con PowerShell. Se desideri seguire una delle dimostrazioni, avrai bisogno di:

  • 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.
  • Diritti di amministratore sul PC Windows
  • A PowerShell code editor such PowerShell ISE or Visual Studio (VS) Code.

Dove Windows Memorizza gli Eventi di Sicurezza

Quando viene eseguita un’azione su un sistema operativo Windows, Windows registra l’azione come un evento in uno o più log degli eventi. I log degli eventi di Windows sono memorizzati nel file system, per impostazione predefinita, nella directory `%SystemRoot%\system32\winevt\logs`. Questa posizione può essere modificata modificando la sottochiave del registro EventLog del log degli eventi corrispondente.

Se desideri vedere dove sono memorizzati i log degli eventi più importanti (Applicazione, Sicurezza e Sistema) nel tuo sistema, copia e incolla il codice seguente in una console di PowerShell o salvalo come script.

Per accedere alla posizione di archiviazione del file di log di Sicurezza, è necessario eseguire il codice come amministratore.

#Presenta i log dell'applicazione, della sicurezza e del sistema in un array.
 $arrLogs = @(
     "Application"
     "Security"
     "System"
 )
 #Utilizza il cmdlet ForEach-Object per individuare ciascun log rispettivo con il cmdlet Get-ItemProperty.
 $arrLogs | ForEach-Object {
     #Utilizza il cmdlet Get-ItemProperty per elencare il percorso del file configurato per il log dell'applicazione, della sicurezza e del sistema.
     Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\$_ -Name File | Select-Object PSChildName,File
 }

La seguente schermata mostra l’output atteso del codice, che visualizza il nome del log e la posizione di archiviazione dei file di log dell’Applicazione, della Sicurezza e del Sistema.

Application, Security, and System audit log location

Politiche di audit: Definizione degli eventi da registrare

Per impostazione predefinita, Windows non registra tutti gli eventi di sicurezza che potrebbero essere necessari per rilevare o investigare una violazione. Per controllare cosa Windows registra o non registra, è necessario definire ed applicare politiche di audit. Una politica di audit è un insieme di istruzioni passate a Windows che indica quali eventi registrare.

Esistono diversi modi per assegnare e lavorare con le politiche di audit, come ad esempio Group Policy. Group Policy funziona bene se devi implementare politiche di audit su molte macchine. Ma in questo articolo, ti concentrerai su un singolo dispositivo, quindi userai lo strumento auditpol. Lo strumento auditpol viene installato con Windows e consente di trovare e impostare le politiche di audit su un sistema Windows.

Trovare le politiche di audit

Ad esempio, per trovare lo stato di tutte le politiche di audit sul tuo sistema Windows, utilizza il parametro /get come mostrato di seguito. Utilizzando il parametro /category seguito da un carattere jolly, auditpol troverà lo stato di tutte le politiche di audit, non solo quelle corrispondenti a una categoria o sotto-categoria specifica.

#Ottenere la configurazione della policy di audit del sistema.
auditpol /get /category:*

Lo screenshot seguente mostra una versione troncata dell’output atteso del codice, visualizzando la categoria di policy di audit della Gestione account, le sottocategorie e lo stato (Impostazione).

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.

Impostazione delle Policy di Audit

Lo strumento auditpol può fare più di visualizzare le impostazioni delle policy di audit. Può anche modificarle utilizzando il comando auditpol /set. Per dimostrare le sezioni future in questo tutorial, apri una console PowerShell come amministratore e esegui il comando sottostante. Questo comando inizia a registrare tutti gli eventi (successo e fallimento) che fanno parte della sottocategoria Logon.

Configurare la sottocategoria Logon obbliga il sistema a registrare gli eventi:

# Imposta gli eventi di accesso per catturare l'attività di successo/fallimento.
auditpol /set /subcategory:"Logon" /success:enable /failure:enable

Ci sono numerose risorse disponibili per assisterti nella configurazione delle migliori pratiche della politica di audit, tra cui i Benchmark del Center for Internet Security (CIS), e le Guide di implementazione tecnica della sicurezza (STIG) dell’Agenzia per i sistemi informativi della difesa (DISA), e le linee guida pubblicate da Microsoft.

Generare i log degli accessi falliti per l’analisi

Questo articolo sarà un tutorial e si aspetta che tu segua attentamente. Se hai configurato Windows per l’audit degli eventi di accesso, generiamo ora alcuni eventi di sicurezza per l’analisi successiva. Più specificamente, generiamo 35 tentativi di accesso falliti che verranno registrati nel registro di sicurezza del tuo sistema per simulare attività di forza bruta.

1. Apri il tuo editor di codice preferito.

2. Copia il seguente codice e incollalo nell’editor di codice. Questo frammento di codice cerca di aprire il processo PowerShell.exe utilizzando il cmdlet Start-Process utilizzando nomi utente e password fasulli.

#Definisci 5 nomi utente da registrare come tentativi di accesso falliti.
 $arrUsers = @(
     "AtaBlogUser1"
     "AtaBlogUser2"
     "AtaBlogUser3"
     "AtaBlogUser4"
     "AtaBlogUser5"
 )
 #Loop attraverso i nomi utente utilizzando ForEach-Object per generare un tentativo di accesso fallito per ognuno.
 $arrUsers | ForEach-Object {
     $securePassword = ConvertTo-SecureString "AtA810GRu13Z%%" -AsPlainText -Force 
     $storedCredential = New-Object System.Management.Automation.PSCredential($_, $securePassword)
     Start-Process -FilePath PowerShell -Credential $storedCredential
 }
 #Genera 30 tentativi di accesso falliti per l'utente 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. Salva lo script PowerShell come Invoke-BogusEvents.ps1 o qualsiasi altro nome tu voglia ed esegui lo script.

Quando eseguito, noterai un errore previsto ripetuto 35 volte che indica Il nome utente o la password non sono corretti.

Authentication failure due to incorrect user name or password.

Se non stai ricevendo l’output previsto, assicurati che il servizio di Logon secondario sia in stato di Esecuzione.

Accesso agli eventi di Windows con PowerShell

Ora che sei sicuro di avere almeno 35 eventi di sicurezza di Windows, vediamo come trovarli con il cmdlet Get-WinEvent di PowerShell.

Potresti essere familiare con il cmdlet Get-EventLog di PowerShell, che viene anche utilizzato per accedere al registro eventi in modo programmato. Get-EventLog utilizza un’interfaccia di programmazione delle applicazioni (API) Win32 che è deprecata e non sarà discussa in questo post.

Apri una console PowerShell come amministratore e invoca il cmdlet Get-WinEvent passandogli il parametro FilterHashtable e MaxEvents come mostrato di seguito.

Il comando seguente interroga il registro di sicurezza del sistema (LogName='Security') per l’evento ID 4625 (ID=4625) e restituisce le prime 10 istanze più recenti (MaxEvents 10).

# Filtra il registro di sicurezza per le prime 10 istanze dell'Evento ID 4625
Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 10

Se tutto va bene, dovresti vedere un output simile al seguente:

10 instances of Event ID 4625

Accesso alle proprietà degli eventi con Get-WinEvent

Nella sezione precedente, hai usato Get-WinEvent per vedere gli eventi di sicurezza di Windows a un livello alto, ma un evento di Windows contiene molte più informazioni. Ogni evento di Windows ha proprietà preziose che puoi usare per un’analisi più approfondita.

Eventi di Windows come XML

Quando Windows registra un evento, viene memorizzato in formato XML. Se è così, perché il tuo comando Get-WinEvent restituisce oggetti PowerShell tipici? Il cmdlet Get-WinEvent legge la nativa API di Windows e traduce gli eventi in oggetti PowerShell per una funzionalità aumentata.

Ogni evento di Windows ha vari attributi che seguono uno specifico schema XML o struttura.

Vedrai di seguito che ogni evento segue una struttura specifica con tre attributi:

  • nome – Il nome della proprietà
  • inType – La definizione del tipo di input o come l’evento accetta un valore
  • outputType – La definizione del tipo di output o come l’evento viene registrato

Trovare i Modelli XML degli Eventi con PowerShell

Come menzionato in precedenza, ogni evento di sicurezza di Windows è memorizzato in XML e ha uno schema specifico, ma com’è fatto questo schema? Scoprilo.

In una delle sezioni precedenti, hai generato alcuni eventi con ID 4625 nel registro eventi di sicurezza. Questo tipo di evento ha attributi specifici che si applicano solo ad esso. Per trovare quegli attributi e come è fatto il modello:

1. Apri una console PowerShell come amministratore se non l’hai già aperta.

2. Esegui nuovamente Get-WinEvent, ma questa volta utilizza il parametro ListProvider specificando il provider che Windows utilizza per registrare gli eventi nel registro eventi di sicurezza e restituisci solo la proprietà Events.

La proprietà Events contiene tutti gli eventi registrati dal provider di elenchi e espone il modello XML per ciascuno di essi.

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

3. Ora che hai il codice per trovare i modelli per tutti i tipi di eventi, restringi la ricerca restituendo solo l’evento associato all’ID 4625.

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

4. Una volta che stai restituendo solo il tipo di evento di accesso con ID 4625, limita ciò a mostrare solo la proprietà Template come segue.

#Ottieni il modello XML dell'evento per le proprietà dell'evento con ID 4625.
 ((Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events | Where-Object -Property ID -eq 4625).Template

La seguente schermata mostra una versione troncata dell’output del codice, identificando il nome della proprietà dell’evento, il tipo di input e il tipo di output. È possibile vedere che l’ID evento 4625 ha proprietà dell’evento con varie definizioni di input e output.

La schermata sottostante evidenzia la proprietà SubjectUserSid dell’ID evento 4625. Questo particolare evento accetta un tipo di input (inType) di win:SID e restituisce l’output (outType) come una stringa, che è come viene memorizzato nel registro di sicurezza.

XML template example

Come PowerShell traduce XML in oggetti

Ora che hai visto come Windows archivia gli eventi in XML e come visualizzare quei modelli in PowerShell, vediamo come PowerShell traduce quel XML in oggetti.

1. Esegui di nuovo il comando Get-WinEvent per restituire il nostro ID evento 4625. Fino a questo punto, nulla di nuovo. Nota che PowerShell mostra solo quattro proprietà, TimeCreated, Id, LevelDisplayName e Message.

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

Per impostazione predefinita, il cmdlet Get-WinEvent non restituisce tutti gli attributi dalla sorgente dati XML dell’evento come oggetto PowerShell.

2. Ora, invia l’output del comando precedente al cmdlet Select-Object e specifica il parametro Property passando un valore di * per mostrare tutte le proprietà.

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

Nota che PowerShell nascondeva molte proprietà diverse. Più specificamente, una proprietà chiamata Properties. La proprietà Properties contiene il valore di ciascun attributo dell’evento che hai visto in precedenza nel modello XML.

Powershell hiding Properties

3. Limita l’output del comando Get-WinEvent sopra per esporre la proprietà Properties. Questa proprietà memorizza tutte le proprietà dell’evento, non le proprietà dell’oggetto PowerShell, in un array.

#Output dell'array delle proprietà dell'evento per la prima istanza dell'ID evento 4625
 $eventProperties = (Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1).properties
 $eventProperties

Sulla sinistra dello screenshot qui sotto è l’output dal comando sopra. L’array contiene i valori per ciascuno degli attributi XML nel template XML sul lato destro dello screenshot.

L’output del codice mostrato nello screenshot comunica che si è verificato un fallimento dell’autenticazione per l’utente AtaBlogUser (TargetUserName) dal sistema Desktop-XXXXX (WorkstationName) usando un indirizzo IP ::1 (IpAddress).

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

Forse vorresti solo restituire il valore per la proprietà dell’evento TargetUserName. Poiché hai già memorizzato tutte le proprietà dell’evento in una variabile chiamata $eventProperties, fai riferimento al quinto indice, che contiene il valore per TargetUserName.

Devi fare riferimento alla proprietà value sull’oggetto proprietà dell’evento individuale per restituire solo il valore (AtaBlogUser). $eventProperties[5].value

$eventProperties[5].value
Event attribute property positions

Le pratiche descritte in questa sezione saranno utilizzate nelle sezioni successive per rintracciare il tentativo di forza bruta che hai simulato in precedenza in questo post.

Rilevare un attacco di forza bruta

Ora sei pronto a utilizzare le tue competenze di PowerShell per rintracciare l’attacco di forza bruta che hai replicato in precedenza in questo post! Mettiamo alla prova le tue competenze simulando ciò che potrebbe sembrare rintracciare un attacco di forza bruta in base a un periodo di tempo specifico.

Supponiamo che ti sia stato segnalato un incidente in cui la tua organizzazione ritiene che qualcuno stia cercando di utilizzare un account amministrativo per accedere a un importante server Windows. Questa attività è iniziata ieri. Devi scoprire il numero di eventi con ID 4625: Un account non è riuscito ad effettuare l’accesso che si sono verificati nelle ultime 24 ore e determinare il tipo di accesso di ciascun evento.

1. Trova tutti gli eventi con ID 4625 (ID=4625) nel log di sicurezza di Windows (LogName="Security") delle ultime 24 ore (StartTime=((Get-Date).AddDays(-1).Date), fino all’ora corrente (Get-Date).

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

2. Ora, conta tutti gli eventi memorizzati nella variabile per determinare se ci sono più eventi di accesso non riusciti di quanto previsto.

$events.Count

Dovresti ora vedere un valore numerico che indica il numero di volte in cui l’evento con ID 4625 è stato trovato nel log degli eventi di sicurezza delle ultime 24 ore.

3. Hai quindi determinato che si è verificato un attacco di forza bruta, ora rintraccia ulteriori informazioni su questi eventi di sicurezza di Windows. Per fare ciò, restituisci solo gli attributi di ciascun evento di tuo interesse.

Come accennato in precedenza, ogni valore per un particolare evento è memorizzato in un array con un indice specifico. Le proprietà interessanti dell’evento per questa demo sono di seguito.

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

Il seguente esempio di codice legge ogni oggetto nella variabile $eventi, raccoglie solo le proprietà interessanti e le concatena in una singola riga.

#Estrai le proprietà TargetUserName, LogonType, WorkstationName e IpAddress da tutte le istanze dell'Evento ID 4625 nelle ultime 24 ore.
 $events | ForEach-Object {
     ## Fa riferimento alla proprietà dell'oggetto proprietà
     ## Restituisci solo il valore degli indici 5, 10, 13 e 19 dall'array delle proprietà
     ## Concatena tutti i valori insieme unendoli con una virgola
     $_.properties[5,10,13,19].value -join ", "
 }

Lo screenshot seguente mostra una versione troncata dell’output atteso del codice, dettagliando un elenco separato da virgole di TargetUserName, LogonType, WorkstationName e IpAddress.

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

Come hai visto dal modello XML precedente, il modello dell’evento ID 4625 ha un attributo LogonType. Questo attributo indica il metodo con cui il tentativo di autenticazione dell’account è stato effettuato. Attraverso ulteriori indagini, hai notato che il LogonType era talvolta diverso.

LogonType attribute

Il valore LogonType è un valore numerico da 2 a 11, ma cosa significa? Effettui una ricerca e scopri cosa significa ciascun valore.

2 – Interattivo – Un utente ha effettuato l’accesso a questo computer.

3 – Rete – Un utente o un computer ha effettuato l’accesso a questo computer dalla rete.

4 – Batch – Il tipo di accesso batch è utilizzato dai server batch, dove i processi possono essere eseguiti per conto di un utente senza il suo intervento diretto.

5 – Servizio – Un servizio è stato avviato dal Gestore dei controlli di servizio.

7 – Sblocco – Questa postazione di lavoro è stata sbloccata.

8 – NetworkCleartext – Un utente ha effettuato l’accesso a questo computer dalla rete. La password dell’utente è stata passata al pacchetto di autenticazione nella sua forma non hashata. Tutti i pacchetti di autenticazione integrati hashano le credenziali prima di inviarle attraverso la rete. Le credenziali non attraversano la rete in testo normale (anche chiamato testo in chiaro).

9 – NuoveCredenziali – Un chiamante ha clonato il proprio token attuale e ha specificato nuove credenziali per le connessioni in uscita. La nuova sessione di accesso ha la stessa identità locale, ma utilizza credenziali diverse per altre connessioni di rete.

10 – RemoteInteractive – Un chiamante ha clonato il proprio token attuale e ha specificato nuove credenziali per le connessioni in uscita. La nuova sessione di accesso ha la stessa identità locale, ma utilizza credenziali diverse per altre connessioni di rete.

11 – CachedInteractive – Un utente ha effettuato l’accesso a questo computer con credenziali di rete memorizzate localmente sul computer. Il controller di dominio non è stato contattato per verificare le credenziali.

Ora che hai una buona comprensione di ciascun LogonType, anziché vedere un valore numerico nell’output, desideri una stringa più descrittiva. Per creare “mappe” in PowerShell, utilizza una 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. Combina Get-WinEvent e la hashtable LogonType con ForEach-Object per creare uno script che restituirà solo le proprietà desiderate con un valore LogonType amichevole, come mostrato di seguito. Il cmdlet Format-Table aggiunge al risultato amichevole all’utente formattando la risposta di PowerShell come una tabella.

#Usa Get-WinEvent per accedere alle proprietà di ogni istanza registrata dell'Evento ID 4625
$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
## Crea il valore numerico per la "mappa"
$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"
}
## Inizia a elaborare ogni oggetto nell'array $events
$events | ForEach-Object {
    ## Cerca il valore numerico nella hashtable
    $logonType = $logonTypes[$_.properties[10].value] 
    #Crea un oggetto PowerShell personalizzato per restituire le proprietà dell'evento rilevante 
    [PSCustomObject]@{     
        TimeCreated = $_.TimeCreated     
        TargetUserName = $_.properties[5].value     
        LogonType = $logonType     
        WorkstationName = $_.properties[13].value     
        IpAddress = $_.properties[19].value 
    }
} | Format-Table -Wrap

A questo punto, hai uno script che restituisce oggetti di tipo PSCustomObject, consentendoti di eseguire molti tipi di analisi diversi! Per finalizzare l’analisi di questo tutorial, dai priorità ai tentativi di fallimento dell’autenticazione per TargetUserName. Per dare priorità ai fallimenti per la proprietà TargetUserName, combina il codice sopra con il cmdlet Group-Object. Usa Sort-Object e il suo interruttore Descending per identificare l’utente che sta causando più problemi.

#Usa Get-WinEvent per accedere alle proprietà di ogni istanza registrata dell'Evento ID 4625
$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
## Crea la mappatura dal valore numerico alla stringa
$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"
}
## Inizia il processo per ogni oggetto nell'array $events
$events | ForEach-Object {
    ## Cerca il valore numerico nell'hashtable
    $logonType = $logonTypes[$_.properties[10].value] 
    #Crea un oggetto PowerShell personalizzato per visualizzare le proprietà dell'evento rilevante 
    [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

Ottimo lavoro! Hai appena utilizzato PowerShell per rilevare il tentativo di forza bruta che hai simulato in precedenza in questo post. Secondo l’output, AtaBlogUser non è riuscito ad autenticarsi 30 volte nelle ultime 24 ore!

AtaBlogUser Logon Failures

Passaggi successivi

In questo tutorial, hai imparato come Windows registra gli eventi, come abilitare la registrazione degli eventi per determinati tipi di eventi e come creare uno strumento PowerShell per interrogare questi eventi.

Con lo script PowerShell che hai ora, come puoi migliorarlo? Come utilizzerai il codice che hai appreso oggi per costruire uno strumento migliore?

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