Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Sentinel-Queries — Raccolta di query KQL | Kitploit
Strumenti/GitHubGitHub/reprise99/sentinel-queries
Strumenti DifensiviThreat IntelligenceApprendimento e FormazioneRisorse CurateRilevamento di AnomalieAnalisi dei Log
GitHubreprise99/sentinel-queries

Sentinel-Queries

Raccolta di query KQL

Vedi Repository
1.6k38267 mesi faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

KQL per Microsoft Sentinel

Alcuni suggerimenti, trucchi ed esempi per l'uso di KQL con Microsoft Sentinel.

  1. Introduzione
  2. L'anatomia di una query KQL
  3. Le basi
    1. Nozioni di base sul tempo
    2. Nozioni di base su Where
    3. Nozioni di base su Project
    4. Nozioni di base su Summarize
    5. Nozioni di base su Render
    6. Nozioni di base su Parse e Split

Introduzione

Kusto Query Language è il linguaggio utilizzato in Azure Monitor, Azure Data Explorer e Azure Log Analytics (ciò che Microsoft Sentinel usa dietro le quinte). Ho sempre trovato utile questa visualizzazione relativa a KQL -

KQL visualized

Vogliamo usare KQL per creare query accurate ed efficienti per trovare minacce, rilevamenti, modelli e anomalie all'interno del nostro set di dati più ampio.

L'anatomia di una query KQL

Prendi come esempio la query qui sotto```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | where AppDisplayName == "Microsoft Teams" | project TimeGenerated, Location, IPAddress, UserAgent

root@kitploit:~
Quando eseguiamo una query come questa, la prima riga dice a Microsoft Sentinel in quale tabella cercare i dati, quindi in questo caso vogliamo cercare nella tabella SigninLogs, che è dove vengono inviati i dati di accesso di Azure AD. Puoi vedere un elenco delle tabelle [qui](https://docs.microsoft.com/en-us/azure/sentinel/data-source-schema-reference).

Microsoft Sentinel eseguirà quindi la query in sequenza, quindi eseguirà ogni riga una per una fino a raggiungere la fine, o a un errore. Quindi, per suddividere la nostra query riga per riga.```kql
SigninLogs
Scarica lo strumento

Quindi prima abbiamo scelto la nostra tabella SigninLogs.```kql SigninLogs | where TimeGenerated > ago(14d)

root@kitploit:~
Successivamente diciamo a Sentinel di esaminare i dati degli ultimi 14 giorni in questa tabella.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"

Successivamente chiediamo a Sentinel di trovare solo i log in cui UserPrincipalName è uguale a "[email protected]"```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0"

root@kitploit:~
Poi cerchiamo solo i log in cui ResultType == 0, che corrisponde a un accesso riuscito ad Azure AD.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| where AppDisplayName == "Microsoft Teams"

Successivamente cerchiamo solo gli accessi a Microsoft Teams.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | where AppDisplayName == "Microsoft Teams" | project TimeGenerated, Location, IPAddress, UserAgent

root@kitploit:~
La nostra ultima riga usa l'operatore project, per restituire solo 4 campi dai nostri log, quindi vedremo solo TimeGenerated, Location, IPAddress e UserAgent restituiti dai nostri dati SigninLogs.

È così che si costruiscono le query, ora le basi.

## Le basi

### Nozioni di base sul tempo

Microsoft Sentinel e KQL sono altamente ottimizzati per i filtri temporali, quindi se conosci il periodo di tempo dei dati che vuoi cercare, dovresti filtrare l'intervallo di tempo subito. Recuperare gli ultimi 14 giorni di log, poi cercare un nome utente come nella query seguente -```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"

È molto più efficiente che cercare prima un nome utente e poi cercare il periodo di tempo in questo modo -```kql SigninLogs | where UserPrincipalName == "[email protected]" | where TimeGenerated > ago(14d)

root@kitploit:~
KQL offre molte opzioni per interrogare periodi di tempo specifici.```kql
SigninLogs
| where TimeGenerated > ago(14d)

Come nel primo esempio, questa ricerca coprirà gli ultimi 14 giorni.```kql SigninLogs | where TimeGenerated > ago(14h)

root@kitploit:~
Puoi anche fare ore.```kql
SigninLogs
| where TimeGenerated > ago(14m)

E minuti.

KQL supporta anche le query tra intervalli di tempo -```kql SigninLogs | where TimeGenerated between (ago(14d) .. ago(7d))

root@kitploit:~
Questo troverà i dati SigninLogs tra 14 giorni e 7 giorni fa.```kql
SigninLogs
| where TimeGenerated between (ago(14h) .. ago(7h))

Tra 14 ore e 7 ore fa.```kql SigninLogs | where TimeGenerated between (ago(14m) .. ago(7m))

root@kitploit:~
E tra 14 minuti e 7 minuti fa.

### Basi di Where

Where è un operatore che userai praticamente in ogni query che scrivi. È così che dici a Microsoft Sentinel di cercare dati specifici. La sintassi è molto importante con l'operatore where. Se usiamo il nostro stesso esempio.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"

Questo cercherà nella nostra tabella SigninLogs, negli ultimi 14 giorni, le corrispondenze esatte in cui il nostro UserPrincipalName è uguale a [email protected]. In KQL, l'operatore == distingue tra maiuscole e minuscole, quindi se cerchi [email protected] e il nome utente è in realtà [email protected], non otterrai alcun risultato. L'equivalente senza distinzione tra maiuscole e minuscole è =```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName = "[email protected]"

root@kitploit:~
Questo troverà tutte le corrispondenze per [email protected] indipendentemente dalla distinzione tra maiuscole e minuscole.

Invece di equals, possiamo anche usare contains.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName contains "reprise_99"

Questo troverà tutte le voci di log in cui UserPrincipalName contiene reprise_99; se avessi dati per [email protected] e [email protected], li troverebbe entrambi. L'operatore contains non è sensibile alle maiuscole, ma puoi usare contains_cs per renderlo sensibile alle maiuscole.

Puoi usare startswith o endswith se stai cercando pattern specifici.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName startswith "reprise_99"

SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName endswith "testdomain.com"

root@kitploit:~
Sia `startswith` che `endswith` non fanno distinzione tra maiuscole e minuscole, ma puoi usare `startswith_cs` o `endswith_cs` per renderle sensibili alle maiuscole/minuscole.

Se stai cercando parole intere (più lunghe di quattro caratteri), in KQL puoi usare l'operatore `has`. Usare `has` è più efficiente di `contains` perché i dati sono indicizzati per te.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where AppDisplayName has "Teams"

Questo troverà tutti i SigninLogs in cui il nome visualizzato dell'applicazione contiene la parola Teams, che potrebbero includere "Microsoft Teams" e "Microsoft Teams Web Client"; entrambi soddisfano la query.

Se stai cercando più parole, puoi usare has_any o has_all.```kql SigninLogs | where TimeGenerated > ago(14d) | where AppDisplayName has_any ("Teams","Outlook")

root@kitploit:~
Questo restituirà risultati in cui il nome visualizzato dell'applicazione contiene "Teams" o "Outlook"```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where AppDisplayName has_all ("Teams","Outlook")

This will return results where the application display name has "Teams" and "Outlook".

Questo restituirà risultati in cui il nome visualizzato dell'applicazione contiene "Teams" e "Outlook".

If you don't know which fields to search in, you can also use wildcards, it is inefficient but may get you on the right track to find what you want.

Se non sai in quali campi cercare, puoi anche usare i caratteri jolly: non è efficiente, ma può metterti sulla strada giusta per trovare ciò che cerchi.```kql SigninLogs | where TimeGenerated > ago(14d) | where * contains "reprise_99"

root@kitploit:~
Questo cercherà nella tabella SigninLogs qualsiasi campo che contenga reprise_99.

Diverse di queste opzioni supportano anche l'uso di ! per invertire la query e trovare risultati in cui non è vera.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName != "[email protected]"

Questa query troverebbe tutti i SigninLogs in cui UserPrincipalName non è uguale a [email protected]```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName !contains "reprise_99"

root@kitploit:~
Questa query troverebbe tutti i SigninLogs in cui UserPrincipalName non contiene reprise_99```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where AppDisplayName !has "Teams"

Questa query troverebbe SigninLogs in cui il nome visualizzato dell'applicazione non contiene "Teams".

Nozioni di base su Project

Project ci consente di selezionare quali colonne vengono restituite nella nostra query e in quale ordine.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | where AppDisplayName == "Microsoft Teams" | project TimeGenerated, Location, IPAddress, UserAgent

root@kitploit:~
Questa query cerca dati di SigninLogs degli ultimi 14 giorni, dove UserPrincipalname è uguale a [email protected], dove ResultType è 0, dove il nome visualizzato dell'applicazione è "Microsoft Teams", quindi per ogni corrispondenza di quella query restituisce TimeGenerated, Location, IPAddress e UserAgent.

Possiamo rinominare le colonne come parte della stessa funzione.```kql
| project LogTime=TimeGenerated, SigninLocation=Location, IP=IPAddress, Agent=UserAgent

Questo restituisce gli stessi dati, ma rinomina le colonne in LogTime, SigninLocation, IP e Agent. Possiamo persino manipolare l'output inline con l'operatore project.```kql | project LocalTime=TimeGenerated+5h, Location, IPAddress, UserAgent

root@kitploit:~
Questo restituisce gli stessi dati, ma cambia il nome TimeGenerated in LocalTime e converte in un fuso orario +5h se lavori in quel fuso orario.

project-away è l'opposto di project e rimuoverà le colonne dalla tua query.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| project-away UserAgent
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| where AppDisplayName == "Microsoft Teams"

In this query we remove UserAgent. Remember, if you remove a column you then can't access it later in your query.

Nozioni di base su Summarize

Summarize produce una tabella che aggrega il contenuto della tua query. Summarize dispone di una serie di funzioni di aggregazione sottostanti. Se riprendiamo la nostra query di esempio, possiamo manipolare i risultati in vari modi usando summarize.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize count() by AppDisplayName

root@kitploit:~
Questa query cercherà nella tabella SigninLogs tutti gli eventi degli ultimi 14 giorni, per qualsiasi corrispondenza per [email protected], dove il risultato è un successo (ResultType == 0) e poi riepilogherà questi eventi in base al nome visualizzato dell'applicazione. Puoi opzionalmente dare un nome alla colonna del risultato.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize AppCount=count() by AppDisplayName

Questo restituisce gli stessi dati ma aggiorna il nome della colonna restituita in AppCount.

Invece di un conteggio totale, puoi riepilogare un conteggio distinto.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize DistinctAppCount=dcount(AppDisplayName) by AppDisplayName

root@kitploit:~
This will return a single record for each distinct application [email protected] signed into.

You can use the arg_max and arg_min functions to return either the newest or oldest record that matches your query.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize arg_max(TimeGenerated, *) by UserPrincipalName

Questa query cerca tutti i log di accesso degli ultimi 14 giorni che hanno [email protected] come UserPrincipalname, che sono andati a buon fine e restituisce il record più recente.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize arg_min(TimeGenerated, *) by UserPrincipalName

root@kitploit:~
Questo è lo stesso ma restituisce il record più vecchio.

Puoi usare countif per fornire logica alle tue somme.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize TeamsLogons=countif(AppDisplayName has "Teams"), SharePointLogons=countif(AppDisplayName has "SharePoint")

Questo riepiloga i dati in due nuove colonne, TeamsLogons dove il nome visualizzato dell'applicazione contiene "Teams" e SharePointLogons dove il nome visualizzato dell'applicazione contiene "SharePoint"

Puoi ulteriormente manipolare i tuoi dati dicendo a KQL di collocare i tuoi dati in 'bin' temporali.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize AppCount=count() by AppDisplayName, bin(TimeGenerated, 1d)

root@kitploit:~
Questo restituisce gli stessi dati del nostro primo esempio di summarize e poi raggruppa quei dati in bin 1d.

Puoi combinare queste funzioni insieme dove utile.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize TeamsLogons=countif(AppDisplayName has "Teams"), SharePointLogons=countif(AppDisplayName has "SharePoint") by bin(TimeGenerated, 1d)

Questa è una combinazione delle nostre funzioni countif e bin, in cui riepiloghiamo in base al nome visualizzato dell'applicazione e inseriamo anche i risultati in bin 1d. Puoi creare un insieme di elementi all'interno di una query.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize AppList=make_set(AppDisplayName) by UserPrincipalName

root@kitploit:~
Questo restituirà un elenco delle applicazioni a cui [email protected] ha effettuato l'accesso, in un elenco chiamato AppList.

Puoi combinarlo con il nostro time bin.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize AppList=make_set(AppDisplayName) by UserPrincipalName, bin(TimeGenerated, 1d)

Questo creerà un elenco delle applicazioni a cui [email protected] ha effettuato l'accesso, suddivise in un elenco per giorno.

Basi di Render

L'operatore render consente a KQL di visualizzare i dati in diversi formati, come grafici a torta, grafici temporali o ad area e grafici a colonne e a barre.

Se usiamo lo stesso esempio della nostra tabella Signinlogs, possiamo vedere come visualizzare i dati in vari modi.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize AppCount=count()by AppDisplayName | render piechart

root@kitploit:~
Questa query riepiloga tutte le applicazioni a cui [email protected] ha effettuato l'accesso negli ultimi 14 giorni, quindi visualizza l'output come grafico a torta.

![KQL Piechart](https://raw.githubusercontent.com/reprise99/Sentinel-Queries/main/Diagrams/render-piechart.png?raw=true)

Puoi anche visualizzarlo come grafico a colonne.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize AppCount=count()by AppDisplayName
| render columnchart

KQL Grafico a colonne

Oppure un grafico a barre.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize AppCount=count()by AppDisplayName | render barchart

root@kitploit:~
![KQL Bar Chart](https://raw.githubusercontent.com/reprise99/Sentinel-Queries/main/Diagrams/render-barchart.png?raw=true)

Per i dati temporali, devi prima riepilogare i tuoi dati in 'bins' di tempo come descritto nella sezione summarize, e puoi quindi visualizzare i tuoi dati su un periodo di tempo.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize SigninCount=count() by bin(TimeGenerated, 1d)
| render timechart

Questo visualizza tutti gli accessi di [email protected] al giorno negli ultimi 14 giorni e li mostra come timechart.

KQL Timechart

Puoi anche usare render come areachart.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize SigninCount=count() by bin(TimeGenerated, 1d) | render areachart

root@kitploit:~
![KQL Areachart](https://raw.githubusercontent.com/reprise99/Sentinel-Queries/main/Diagrams/render-areachart.png?raw=true)

I grafici a colonne e a barre possono essere utilizzati anche con dati temporali. Otterrai una colonna o una barra per ogni 'bin' di tempo nell'arco del periodo di tempo più ampio.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize SigninCount=count() by bin(TimeGenerated, 1d)
| render columnchart

Questa è la stessa query del nostro timechart, ma renderizzata come un grafico a colonne con una colonna per giorno.

Grafico a colonne temporale KQL```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize SigninCount=count() by bin(TimeGenerated, 1d) | render barchart

root@kitploit:~
E un grafico a barre.

![KQL Time Bar Chart](https://raw.githubusercontent.com/reprise99/Sentinel-Queries/main/Diagrams/render-timebarchart.png?raw=true)```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize SigninCount=count() by AppDisplayName, bin(TimeGenerated, 1d)
| render columnchart

Questa query trova tutti gli accessi al nostro account, conta gli accessi per applicazione, quindi crea una singola colonna per ogni giorno.

KQL Time Column Chart Stacked

Se vuoi che ogni applicazione abbia la propria colonna, puoi impostarlo come non accatastato.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | summarize SigninCount=count() by bin(TimeGenerated, 1d) | render columnchart with (kind=unstacked)

root@kitploit:~
![KQL Time Column Chart Unstacked](https://raw.githubusercontent.com/reprise99/Sentinel-Queries/main/Diagrams/render-timecolumnchartunstacked.png?raw=true)

Puoi anche rinominare l'asse e il titolo del tuo grafico in linea con KQL.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| summarize SigninCount=count() by AppDisplayName, bin(TimeGenerated, 1d)
| render columnchart with (kind=unstacked, ytitle="Total Sign Ins", xtitle="Day", title="Application Signins Per Day")

Grafico a colonne temporali KQL non impilato e rinominato

Puoi combinare la logica nelle tue azioni summarize per creare contenuti dinamici per il tuo operatore render.```kql SigninLogs | where TimeGenerated > ago(14d) | where ResultType == "0" | summarize TeamsCount=countif(AppDisplayName has "Teams"), OneDrive=countif(AppDisplayName has "OneDrive"), SharePointCount=countif(AppDisplayName has "SharePoint") by bin(TimeGenerated, 1d) | render columnchart with (kind=unstacked, ytitle="Sign In Count", xtitle="Day", title="Teams vs OneDrive vs SharePoint Sign Ins Per Day")

root@kitploit:~
Questa query cerca tutti gli accessi al tuo tenant, quindi conta tre gruppi: uno in cui il nome visualizzato dell'applicazione contiene "Teams", uno in cui il nome visualizzato dell'applicazione contiene "OneDrive" e uno in cui il nome visualizzato dell'applicazione contiene "SharePoint" per ogni giorno degli ultimi 14 giorni, quindi li visualizza come un grafico a colonne non impilate.

![Grafico a colonne temporali KQL Outlook, OneDrive, SharePoint](https://raw.githubusercontent.com/reprise99/Sentinel-Queries/main/Diagrams/render-timecolumn-outlookonedrivesharepoint.png?raw=true)

### Nozioni di base su Parse e Split

Parse e split sono due modi diversi per estendere una stringa di dati a più colonne in base alle corrispondenze. Molti log inseriti in Microsoft Sentinel possono arrivare come un'unica lunga stringa (ad esempio sysmon); parse e split consentono di manipolarli in dati leggibili.

Per questi esempi, useremo i seguenti dati di test.```kql
let ExampleText = datatable(TestData:string)
[
'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account'
];

Questi dati sono una singola stringa che si presenta così.

Parse

Possiamo estrarre corrispondenze di dati specifici con quanto segue```kql let ExampleText = datatable(TestData:string) [ 'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account' ]; ExampleText | parse TestData with * 'Name=' DisplayName ',' * | project DisplayName

root@kitploit:~
Questo analizzerà tutti i dati tra Name= e , in una nuova colonna chiamata 'DisplayName'.

![Analisi 1](https://raw.githubusercontent.com/reprise99/Sentinel-Queries/main/Diagrams/parse1.png?raw=true)

Puoi estrarre più colonne nello stesso comando facendo corrispondere la stringa.```kql
let ExampleText = datatable(TestData:string)
[
'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account'
];
ExampleText
| parse TestData with * 'Name=' DisplayName ',UPNSuffix=' DomainSuffix ',AadTenantId=' AzureADTenantId ',' *
| project DisplayName, DomainSuffix, AzureADTenantId

Questo esegue il parse di tre nuove colonne - DisplayName, DomainSuffix e AzureADTenantId

Parse 2

Ricordando che KQL esegue le sue operazioni in sequenza, una volta effettuato il parse possiamo eseguire un nuovo parse sulla colonna appena creata.```kql let ExampleText = datatable(TestData:string) [ 'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account', ]; ExampleText | parse TestData with * 'Name=' DisplayName ',UPNSuffix=' DomainSuffix ',AadTenantId=' AzureADTenantId ',' * | project DisplayName, DomainSuffix, AzureADTenantId | parse DomainSuffix with * '.' TopLevelDomain | project DisplayName, DomainSuffix, TopLevelDomain, AzureADTenantId

root@kitploit:~
Questo analizza ulteriormente il nostro dominio per trovare il dominio di primo livello, in questo caso un .com

![Parse 3](https://raw.githubusercontent.com/reprise99/Sentinel-Queries/main/Diagrams/parse3.png?raw=true)

Quando si utilizza l'operatore parse, KQL scorrerà tutte le righe di dati e restituirà anche i risultati in cui non c'è corrispondenza. Quindi, a seconda della struttura dei dati, potresti ritrovarti con molte righe di dati vuote. Se espandiamo i dati di esempio per includere un'altra riga di dati, con nomi diversi, ed eseguiamo la stessa query, vedrai risultati vuoti.```kql
let ExampleText = datatable(TestData:string)
[
'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account',
'Display=Reprise99,UPN=testdomain.com,AadDirectoryId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadObjectId=cf6f2df6-b754-48dc-b7bc-c8339caf211,Name=Test User,AccountType=account'
]
;
ExampleText
| parse TestData with * 'Name=' DisplayName ',UPNSuffix=' DomainSuffix ',AadTenantId=' AzureADTenantId ',' *
| project DisplayName, DomainSuffix, AzureADTenantId
| parse DomainSuffix with * '.' TopLevelDomain
| project DisplayName, DomainSuffix, TopLevelDomain, AzureADTenantId

Parse 4

Per contrastare questo problema, puoi usare l'operatore 'parse-where', che restituisce solo i risultati in cui sono presenti corrispondenze con la tua query.```kql let ExampleText = datatable(TestData:string) [ 'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account', 'Display=Reprise99,UPN=testdomain.com,AadDirectoryId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadObjectId=cf6f2df6-b754-48dc-b7bc-c8339caf211,Name=Test User,AccountType=account' ] ; ExampleText | parse-where TestData with * 'Name=' DisplayName ',UPNSuffix=' DomainSuffix ',AadTenantId=' AzureADTenantId ',' * | project DisplayName, DomainSuffix, AzureADTenantId | parse DomainSuffix with * '.' TopLevelDomain | project DisplayName, DomainSuffix, TopLevelDomain, AzureADTenantId

root@kitploit:~
Possiamo vedere che siamo tornati a un singolo risultato dove avevamo una corrispondenza nella nostra analisi.

![Parse 5](https://raw.githubusercontent.com/reprise99/Sentinel-Queries/main/Diagrams/parse5.png?raw=true)

Split separa una stringa di testo in un array basandosi su un delimitatore. Se torniamo ai nostri dati di test originali, possiamo dividere in base al segno di virgola.```kql
let ExampleText = datatable(TestData:string)
[
'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account',
]
;
ExampleText
| extend SplitData = split(TestData,',')
| project SplitData

Ci verrà restituito un array con la nostra stringa suddivisa.

Split 1

Split è consapevole degli indici, quindi se i tuoi dati sono nello stesso ordine, puoi suddividere direttamente in nuove colonne.```kql let ExampleText = datatable(TestData:string) [ 'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account', ] ; ExampleText | extend Name = split(TestData,',')[0] | extend DomainSuffix = split(TestData,',')[1] | extend AzureADTenantId = split(TestData,',')[2] | extend AzureADUserId = split(TestData,',')[3] | extend DisplayName = split(TestData,',')[4] | extend AccountType = split(TestData,',')[5] | project Name, DomainSuffix, AzureADTenantId, AzureADUserId, DisplayName, AccountType

root@kitploit:~
Se conosciamo la posizione dei nostri dati all'interno della stringa, possiamo suddividerla direttamente in colonne denominate.

![Split 2](https://raw.githubusercontent.com/reprise99/Sentinel-Queries/main/Diagrams/split2.png?raw=true)

Una volta suddivisi i nostri dati, possiamo interrogarli come se fossero stati strutturati dall'inizio. Quindi, se aggiungiamo un secondo record ai nostri dati e poi interroghiamo per corrispondenze specifiche, troveremo ciò che cerchiamo.```kql
let ExampleText = datatable(TestData:string)
[
'Name=Reprise99,UPNSuffix=testdomain.com,AadTenantId=345c1234-a833-43e4-1d34-123440a5bcdd1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User,Type=account',
'Name=Reprise103,UPNSuffix=testdomain.com,AadTenantId=331c1234-a841-43e5-1d31-12220a5bcee1,AadUserId=cf6f2df6-b754-48dc-b7bc-c8339caf211,DisplayName=Test User 2,Type=account'
]
;
ExampleText
| extend Name = split(TestData,',')[0]
| extend DomainSuffix = split(TestData,',')[1]
| extend AzureADTenantId = split(TestData,',')[2]
| extend AzureADUserId = split(TestData,',')[3]
| extend DisplayName = split(TestData,',')[4]
| extend AccountType = split(TestData,',')[5]
| project Name, DomainSuffix, AzureADTenantId, AzureADUserId, DisplayName, AccountType
| where Name contains "Reprise99"

Otteniamo un solo risultato, dove Name contiene "Reprise99", il nostro secondo record dove Name contiene "Reprise103" non viene trovato.

Split 3