
Collection de requêtes KQL
Quelques astuces, trucs et exemples pour utiliser KQL avec Microsoft Sentinel.
Kusto Query Language est le langage utilisé dans Azure Monitor, Azure Data Explorer et Azure Log Analytics (ce que Microsoft Sentinel utilise sous le capot). J'ai toujours trouvé cette visualisation de KQL utile -

Nous voulons utiliser KQL pour créer des requêtes précises et efficaces afin de détecter les menaces, les détections, les modèles et les anomalies au sein de notre jeu de données plus large.
Prenons la requête ci-dessous comme exemple```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | where AppDisplayName == "Microsoft Teams" | project TimeGenerated, Location, IPAddress, UserAgent
Lorsque nous exécutons une requête comme celle-ci, la première ligne indique à Microsoft Sentinel dans quelle table chercher les données. Dans ce cas, nous voulons interroger la table SigninLogs, qui est l'endroit où les données de connexion Azure AD sont envoyées. Vous pouvez consulter une liste des tables [ici](https://docs.microsoft.com/en-us/azure/sentinel/data-source-schema-reference).
Microsoft Sentinel exécutera ensuite votre requête de manière séquentielle, c'est-à-dire qu'il traitera chaque ligne une par une jusqu'à la fin, ou jusqu'à ce qu'une erreur survienne. Décomposons donc notre requête ligne par ligne.```kql
SigninLogs
Donc d'abord, nous avons choisi notre table SigninLogs.```kql SigninLogs | where TimeGenerated > ago(14d)
Ensuite, nous demandons à Sentinel d'examiner les 14 derniers jours de données dans cette table.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
Ensuite, nous demandons à Sentinel de ne trouver que les journaux où UserPrincipalName est égal à "[email protected]"```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0"
Ensuite, nous recherchons uniquement les journaux où ResultType == 0, ce qui correspond à une connexion réussie à Azure AD.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
| where ResultType == "0"
| where AppDisplayName == "Microsoft Teams"
Ensuite, nous recherchons uniquement les connexions à Microsoft Teams.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName == "[email protected]" | where ResultType == "0" | where AppDisplayName == "Microsoft Teams" | project TimeGenerated, Location, IPAddress, UserAgent
Notre dernière ligne utilise l'opérateur project, pour ne renvoyer que 4 champs de nos journaux, afin que nous voyions uniquement les TimeGenerated, Location, IPAddress et UserAgent renvoyés de nos données SigninLogs.
Voilà comment vous construisez des requêtes, passons maintenant aux bases.
## Les bases
### Les bases du temps
Microsoft Sentinel et KQL sont hautement optimisés pour les filtres de temps, donc si vous connaissez la période des données que vous souhaitez rechercher, vous devez filtrer la plage de temps immédiatement. Récupérer les 14 derniers jours de journaux, puis rechercher un nom d'utilisateur comme la requête ci-dessous -```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
Est beaucoup plus efficace que de rechercher d'abord un nom d'utilisateur puis la période comme ceci -```kql SigninLogs | where UserPrincipalName == "[email protected]" | where TimeGenerated > ago(14d)
KQL propose de nombreuses options pour interroger des périodes de temps spécifiques.```kql
SigninLogs
| where TimeGenerated > ago(14d)
Comme dans le premier exemple, cela recherchera les 14 derniers jours.```kql SigninLogs | where TimeGenerated > ago(14h)
Vous pouvez également faire des heures.```kql
SigninLogs
| where TimeGenerated > ago(14m)
Et les minutes.
KQL prend également en charge les requêtes entre plages de temps -```kql SigninLogs | where TimeGenerated between (ago(14d) .. ago(7d))
Cela trouvera les données SigninLogs entre il y a 14 jours et il y a 7 jours.```kql
SigninLogs
| where TimeGenerated between (ago(14h) .. ago(7h))
Entre il y a 14 heures et il y a 7 heures.```kql SigninLogs | where TimeGenerated between (ago(14m) .. ago(7m))
Et entre il y a 14 minutes et il y a 7 minutes.
### Les bases de Where
Where est un opérateur que vous utiliserez dans pratiquement chaque requête que vous écrirez. C'est ainsi que vous indiquez à Microsoft Sentinel de rechercher des données spécifiques. La syntaxe est très importante avec l'opérateur where. Si nous utilisons notre même exemple.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName == "[email protected]"
Cela recherchera dans notre table SigninLogs, sur les 14 derniers jours, les correspondances exactes où notre UserPrincipalName est égal à [email protected]. En KQL, == est sensible à la casse, donc si vous recherchez [email protected] alors que le nom d'utilisateur est en réalité [email protected], vous n'obtiendrez aucun résultat. L'équivalent insensible à la casse est =```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName = "[email protected]"
Cela trouvera toutes les correspondances pour [email protected], indépendamment de la sensibilité à la casse.
Au lieu de equals, on peut aussi utiliser contains.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where UserPrincipalName contains "reprise_99"
Cela permettra de trouver toutes les entrées de journal où le UserPrincipalName contient reprise_99 ; si vous disposiez de données [email protected] et [email protected], il les trouverait toutes les deux. L'opérateur contains n'est pas sensible à la casse, mais vous pouvez utiliser contains_cs pour le rendre sensible à la casse.
Vous pouvez utiliser startswith ou endswith si vous recherchez des modèles particuliers.```kql SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName startswith "reprise_99"
SigninLogs | where TimeGenerated > ago(14d) | where UserPrincipalName endswith "testdomain.com"
Ni startswith ni endswith ne sont sensibles à la casse, mais vous pouvez utiliser startswith_cs ou endswith_cs pour les rendre sensibles à la casse.
Si vous recherchez des mots entiers (de plus de quatre caractères), dans KQL vous pouvez utiliser l'opérateur has. Utiliser 'has' est plus efficace que 'contains' car les données sont indexées pour vous.```kql
SigninLogs
| where TimeGenerated > ago(14d)
| where AppDisplayName has "Teams"
Cela trouvera tous les SigninLogs où le nom d'affichage de l'application contient le mot Teams, ce qui peut inclure « Microsoft Teams » et « Microsoft Teams Web Client », les deux satisfaisant la requête.