Analisi delle trascrizioni PowerShell

Di Raido Karro e Liisa Tallinn
28 maggio 2020

Anche se non stai usando PowerShell nelle tue macchine Windows, i tuoi avversari e pen-tester lo sono. Perché utilizzare strumenti hax0r personalizzati quando ogni macchina Windows è dotata di un ambiente di scripting integrato? Powershell consente all’attaccante di fare praticamente qualsiasi cosa senza lasciare tracce sui dischi. È un errore non amare PowerShell come attaccante e un errore non amare PowerShell logs come difensore.

Quanto segue è un tutorial di analisi e query che utilizza l’analizzatore di log gratuito di SpectX per ottenere statistiche generali e approfondimenti specifici dai registri di trascrizione di PowerShell che sono notoriamente difficili da analizzare. Non è necessario importare o ingerire i file dalla directory di output corrente: SpectX esegue le query direttamente sui registri grezzi. La creazione di una vista pulita dai registri grezzi richiede solo un paio di minuti.

Abbiamo caricato un piccolo set di file di trascrizione nel nostro repository S3 pubblico – sentitevi liberi di eseguire le query di seguito su questi dati di esempio. Le domande che abbiamo posto nelle query hanno lo scopo di esplorare la linea di base e individuare comportamenti anormali (potenzialmente dannosi). Quali sono stati i comandi principali eseguiti? Quando sono stati eseguiti la maggior parte dei comandi? Quando sono stati eseguiti per la prima volta? Quali erano le uscite dei comandi che apparivano sulla console durante l’esecuzione del comando – qualcosa di insolito? Chi sono i migliori utenti? Eventuali utenti che eseguono comandi che non dovrebbero essere in esecuzione? Top applicazioni host? Quanti comandi per ora / giorno / settimana? Che dire dei comandi offuscati? E così via – una volta che si ottiene un blocco di query SpectX, le domande di follow-up non si fermano mai.

Indice

Informazioni sulle trascrizioni
Come attivare la registrazione delle trascrizioni
Formato dei registri delle trascrizioni
Lettura e analisi dei registri con SpectX
Chi? Che? Quando? Come? – le query

Trascrizioni Sanno tutto… o Quasi ∞

Ci sono 3 tipi di registrazione che possono essere abilitati per PowerShell: registrazione del modulo, blocco di script e trascrizione. Poiché i primi due possono essere visualizzati come eventi di Windows, è spesso consigliabile leggere manualmente i file di testo di trascrizione solo quando si verifica un problema derivante dal monitoraggio dei primi due. Allo stesso tempo, le informazioni contenute nelle trascrizioni sono le più complete delle tre e i file di testo flat sono molto più efficienti di archiviazione rispetto agli eventi di Windows prodotti dalla registrazione di moduli e blocchi di script. Ad esempio, l’esecuzione di un semplice host di scrittura “hello world” o in questo caso “All You Need is Logs” produce 22 eventi Windows dalla registrazione del modulo e del blocco di script, ma le stesse informazioni più l’output del comando vengono registrate anche in questa trascrizione PowerShell da 1 KB:

**********************
Windows PowerShell transcript start
Start time: 20200521135800
Username: DESKTOP-7KL6SCQ\Loki
RunAs User: DESKTOP-7KL6SCQ\Loki
Configuration Name:
Machine: DESKTOP-7KL6SCQ (Microsoft Windows NT 10.0.18363.0)
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Process ID: 5624
PSVersion: 5.1.18362.752
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.18362.752
BuildVersion: 10.0.18362.752
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
**********************
Command start time: 20200521135818
**********************
PS C:\Users\Loki> write-host "All You Need is Logs"
All You Need is Logs
**********************
Command start time: 20200521135821
**********************
PS C:\Users\Loki> exit
**********************
Windows PowerShell transcript end
End time: 20200521135821
**********************

Il problema è che i registri di trascrizione sono stati storicamente progettati per scopi di debug, cioè per gli esseri umani piuttosto che per le macchine da leggere. Il loro contenuto è quasi a forma libera e notoriamente difficile da analizzare. Scavando nel Web, è possibile trovare alcuni tentativi sul Web di ingerire le trascrizioni in uno strumento di elaborazione del registro, ma nessuno di essi raggiunge l’estrazione di comandi e output di comandi in campi separati. Questo è un peccato perché gli output dei comandi vengono registrati solo per le trascrizioni e le intuizioni su ciò che è realmente accaduto a seguito dei comandi PS possono essere preziose.
Inserisci SpectX. Saltando la fase di ingestione e usando i blocchi di costruzione nel linguaggio di analisi, può estrarre non solo i campi utente e host/macchina nel prologo, ma anche i tempi di inizio dei comandi, i comandi e gli output. Poiché il parser di SpectX viene applicato ai file di registro grezzi durante il runtime della query, significa anche che è possibile eseguire il debug, migliorare e correggere il parser con ogni query nel caso in cui il formato del registro cambi. E i registri di trascrizione di PowerShell sono davvero volatili.
Quando si inizia a scrivere questo post, abbiamo creduto trascrizioni PowerShell sono onnipotente e registrare tutto. Tuttavia, giocando con comandi e output, si è scoperto che c’è un’eccezione. Quando si esegue uno script PS da un URL, la trascrizione cattura il comando (incluso l’URL) e l’output, ma ti lascia completamente cieco per quanto riguarda il contenuto dello script o dei comandi eseguiti dallo script. Ad esempio, per sapere cosa ha fatto questo particolare script eseguito da un URL, è necessario passare agli eventi di Windows prodotti dalla registrazione del modulo.

**********************
Windows PowerShell transcript start
Start time: 20200521141014
Username: DESKTOP-7KL6SCQ\Loki
RunAs User: DESKTOP-7KL6SCQ\Loki
Configuration Name:
Machine: DESKTOP-7KL6SCQ (Microsoft Windows NT 10.0.18363.0)
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Process ID: 788
PSVersion: 5.1.18362.752
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.18362.752
BuildVersion: 10.0.18362.752
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
**********************
Command start time: 20200521141021
**********************
PS C:\Users\Loki> iex (New-Object "net.webclient").DownloadString("http://spectx.com/test.ps1")
All You Need is Logs!
**********************
Command start time: 20200521141023
**********************
PS C:\Users\Loki> exit
**********************
Windows PowerShell transcript end
End time: 20200521141023
**********************

Come attivare la registrazione della trascrizione di PowerShell ∞

1. Aprire il menu Start e digitare ‘gpedit’ per aprire una finestra Editor Criteri di gruppo locale

2. Passare a Modelli di amministrazione > Componenti di Windows > Windows PowerShell

3. Clicca su ‘Attiva la trascrizione di PowerShell’

4. Selezionare ‘Abilitato’ e specificare il percorso della directory di output. Importante! Seleziona la casella per attivare le intestazioni di invocazione. Questo registrerà ogni comando eseguito con un’ora di inizio del comando.

5. Fare clic su OK
6. Aprire una finestra di PowerShell per verificare se la registrazione funziona. Digitare un comando, ad es. un semplice host di scrittura: ‘tutto ciò di cui hai bisogno sono i log’ seguito da ‘exit’.

7. Verificare se la directory di output specificata nel passaggio 4 contiene una trascrizione con i timestamp e le azioni nel passaggio 6.

A lungo termine è una buona idea centralizzare la raccolta di trascrizioni di PowerShell per analizzarle su larga scala, ad esempio controlla questo tutorial di @ dan_franciscus nel blog 4sysops.

Transcript Log Format ∞

Alcune parole sul formato del registro e sulla logica del parser. Se preferisci fare query e non sei interessato all’anatomia dei file di registro e del parser, vai alla sezione successiva. Ecco un esempio di un registro di trascrizione PS v. 5.1 non elaborato:

**********************
Windows PowerShell transcript start
Start time: 20171030223248
Username: WIN-FT17VBNL4B2\Administrator
RunAs User: WIN-FT17VBNL4B2\Administrator
Machine: WIN-FT17VBNL4B2 (Microsoft Windows NT 10.0.14393.0)
Host Application: C:\Windows\system32\WindowsPowerShell\v1.0\PowerShell.exe
Process ID: 4268
PSVersion: 5.1.14393.1770
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.14393.1770
BuildVersion: 10.0.14393.1770
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
**********************
Command start time: 20171030223255
**********************
PS C:\Users\Administrator> echo test
test
**********************
Command start time: 20171030223256
**********************
PS C:\Users\Administrator> exit
**********************
Windows PowerShell transcript end
End time: 20171030223256
**********************

Un file di trascrizione viene creato con ogni sessione PowerShell. La prima sezione della trascrizione è un prologo contenente campi specifici della sessione come l’ora di inizio della sessione, l’utente, la versione di PowerShell ecc. Quindi, dopo una riga di asterischi, la raccolta di comandi e output viene eseguita durante questa sessione. Infine, una sezione epilogo opzionale alla fine del file con l’ora di fine sessione ma solo se la sessione è stata terminata con un comando di uscita (e non chiudendo la finestra).

Il numero di comandi tra il prologo e l’epilogo varia. Questo è il motivo per cui abbiamo adottato un approccio in due fasi: prima analizzare il prologo, l’epilogo e i comandi-output in blocco; quindi estrarre i comandi e gli output in campi separati nel livello di query.

Come leggere e analizzare le trascrizioni ∞

SpectX legge i dati direttamente dai file di log grezzi e li analizza in fase di runtime. Nel modello, assumiamo che tu abbia attivato le intestazioni di invocazione, ovvero ogni comando PowerShell viene registrato con un’ora di inizio del comando. Per visualizzare le trascrizioni come una tabella pulita:

1. Scarica e installa gratuitamente SpectX.

2. Copia questa query di base (Github) nella finestra di query

3. Modificare il percorso sulla riga 47 in modo che corrisponda alla directory di output dei file di registro di trascrizione. Non modificare le variabili temporali nel percorso: ciò consentirà di filtrare i registri in base ai timestamp nel percorso del file. Ad esempio, se il percorso di uno dei file di trascrizione è

C:\Logs\powershell200405\PowerShell_transcript.WS01.5OoA7WLR.20200405152828.txt

, l’URI nella query SpectX che punta a tutti i file di registro con un percorso simile C:\Logs\powershell cartella sarebbe:

file:/C:/Logs/powershell/$yyyy$$MM$$dd$/PowerShell_transcript.*.$yyyy$$MM$$dd$$HH$$mm$$ss$.txt

4. Modificare il numero di giorni nello script init all’inizio dello script (righe 2-4) se si desidera dare un’occhiata ai registri più vecchi/più recenti.

5. Premi esegui. I risultati dovrebbero essere simili a questo:

Chi? Che? Quando? Come? Le query ∞

Quando fai domande dai log, stai cercando il noto o lo sconosciuto. Cercare il noto è facile-basta filtrare i dati necessari. Ad esempio:

| filter(lower(output) CONTAINS 'error') 

ti dà tutti i comandi che contengono la stringa ‘error’ nell’output.

Se si desidera esaminare un periodo di tempo specifico, modificare il blocco init contenente i timestamp all’inizio dello script di query di base.

Diventa più interessante se stai cercando l’ignoto e vuoi approfondire qualcosa di insolito. Il primo passo qui è stabilire la linea di base-il solito e quindi filtrare come qualcosa che non ti interessa. Ad esempio, un trucco accurato è quello di guardare quando è stato eseguito un comando per la prima volta e quindi concentrarsi sui comandi che sono stati visti per la prima volta più tardi di altri (vedere la query di esempio n.2 di seguito).
Copia e incolla queste query una per una fino alla fine della query di base. Fare doppio clic su un record per vedere tutto il suo contenuto, fare clic destro su un campo per applicare filtri (negativi).

Approfondimenti sui comandi e sulle uscite dei comandi

1. Comandi principali

| select(cnt:count(*), command)
| group(@2)
| sort(cnt DESC)

2. Quando è stata la prima volta che è stato eseguito un comando?

| select(min(commandStartTime),count(*),command,*)
| group(command)
| sort(min_commandStartTime)

3. Comando superiore-coppie di output

| select(cnt:count(*), command,output)
| group(command,output)
| sort(cnt DESC)

4. Numero di comandi all’ora

| select(count(*),trunc_cmd_start:commandStartTime)
| group(trunc_cmd_start)

5. Comandi che probabilmente sono stati scritti manualmente, cioè comandi che iniziano con ‘ c:\\’

| select(start_time, end_time, Username, RunAs_User, Machine, PID, PSVersion, commandText)
| filter(lower(commandText) contains 'c:\')

6. Analizzare nuovamente il campo di output per rilevare gli indirizzi IP in commandText

| select(parse("DATA* IPADDR:ip DATA*", commandText), commandText, *)
| filter_out(ip IS NULL)

7. Trova la stringa ‘download’ all’interno di command_output anche se è offuscata (rimuovi la punteggiatura). Ad esempio, se il comando invoke era simile a questo:

| select(deobf_commandText:lower(REPLACEALL(commandText, "" , '')) ) 
| filter(deobf_commandText contains 'download')

Statistiche generiche

8. Quante sessioni PowerShell all’ora?

| select(start_time:start_time,count(*))
| group(start_time)

9. TOP 100 Nomi utente

| select(Username, cnt:count(*))
| group(@1)
| sort(cnt DESC)
| limit(100)

10. Quanti record ha generato un utente per macchina?

| select(Username,Machine,cnt:count(*))
| group(@1,@2)
| limit(100)

11. Top applicazioni host-elenco delle applicazioni che eseguono PowerShell, compresi i parametri di comando aggiuntivi.

| select(cnt:count(*),Host_Application)
| group(@2)
| sort(cnt DESC)
| limit(100)

12. Top 100 applicazioni host per utente

| select(Host_Application, Username, cnt:count(*))
| group(@1,@2)
| sort(cnt DESC)
| limit(100)

13. Dai un’occhiata più da vicino alla punteggiatura nei comandi. I comandi che sono valori anomali (il conteggio è piccolo) meritano uno sguardo dettagliato.

| select(PUNCT(command, 64, false), cnt:count(*),uniq_commands:ARRAY_LEN(ARRAY_UNIQ(ARRAY_AGG(command))),commands_array:ARRAY_UNIQ(ARRAY_AGG(command)))
| group(@1)
| sort(cnt)
| limit(100)

Conclusione

Anche se i registri di trascrizione PowerShell non sono facili da leggere per le macchine, le informazioni che contengono sono complete e vale la pena analizzare. Dopo tutto, PowerShell è uno strumento per automatizzare e configurare quasi tutte le attività in Windows – è un ‘anello per governare tutti’. Dare un’occhiata focalizzata alle statistiche di PowerShell, ai comandi e alle loro uscite è un buon modo per assicurarsi che l’anello non sia nelle mani sbagliate o usato all’oscuro.
Ringraziamenti
Grazie Taavi @ Ha chiarito la sicurezza. Trascrizioni dal corso Hunt the Hacker sono stati un ottimo punto di partenza per questo articolo.

Torna agli articoli

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.