Microsoft 365 Defender Advanced Hunting with PowerShell

Hi All,

You might already know, that i am a big Fan of Defender for Office 365 Advanced Hunting.
It's easy and fast to analyze the last 30 Days of your Messaging Logs.

Defender for Office 365 Advanced Hunting

I've published some of the KQL Querys in my GitHub Rpo

You can find Advanced Hunting it in de Microsoft 365 Defender Portal


To Access these Querys with PowerShell we need to have an Azure Active Directory Application




It's documented by the following Links, how to Access these API's.

Access the Microsoft 365 Defender APIs

Microsoft 365 Defender Advanced hunting API

You need to select "APIs my organization uses" and search for "Microsoft Threat Protection"


For Delegated permissions you need "AdvancedHunting.Read" Permission


For Aplication permissions you need "AdvancedHunting.Read.All" Permission


After that you need to Admin Consent (Global Administrator  / Application Administrator / Cloud Application Administrator)



Note: The code of this Script has also been published to my GitHub Repo

First we need to get an Access Token.I use the MSAL.PS PowerShell Module.To inspect the Token i use the JWTDetails PowerShell Module

Install-Module MSAL.PS
Install-Module JWTDetails


This is the Code to Authenticate with MSAL.PS with the Certificate where i have the private Key from my Current User Certificate Store. Note that i use a Scope to get the Token.

#Application Authentication
$AppId = "23299ad3-9e6f-4390-a121-1e5a394a6914" #PSSecurity
$TenantId = "icewolfch.onmicrosoft.com"
$ThumbPrint = "07EFF3918F47995EB53B91848F69B5C0E78622FD"
$Certificate = Get-ChildItem Cert:\CurrentUser\My\ | Where-Object {$_.Thumbprint -eq $ThumbPrint}
Import-Module MSAL.PS
Clear-MsalTokenCache
$Scopes = "https://api.security.microsoft.com/.default"
$Token = Get-MsalToken -ClientId $AppId -ClientCertificate $Certificate  -TenantId $TenantId -Scopes $Scopes
$AccessToken = $Token.AccessToken
Get-JWTDetails -token $AccessToken


Note that under Roles the "AdvancedHunting.Read.All" Permission is visible.


Now i can create the Query

#KQL Query Multiline
$query = @'
//TOP 10 URL Domains
EmailUrlInfo
| summarize count() by UrlDomain
| top 10 by count_
'@


I have th add the AccessToken to the Header and convert the Body to JSON to include the KQL Query as JSON.
Then a HTTP Post can be invoked

$uri = "https://api.security.microsoft.com/api/advancedhunting/run"
$Headers = @{
    "Content-Type" = "application/json"
    "Authorization" = "Bearer "+ $AccessToken
    }
$Body = ConvertTo-Json -InputObject @{ 'Query' = $query }
$Response = Invoke-RestMethod -Method Post -Uri $uri -Headers $Headers -Body $Body
If ($Null -ne $Response)
{
    $Response.Results
}



If you want to use delegated Authentication (Authenicate as User) you still need the App.

#Delegated Authentication
$AppId = "23299ad3-9e6f-4390-a121-1e5a394a6914" #PSSecurity
$TenantId = "icewolfch.onmicrosoft.com"
Import-Module MSAL.PS
Clear-MsalTokenCache
$Scopes = "https://api.security.microsoft.com/.default"
$Token = Get-MsalToken -ClientId $AppId -TenantId $TenantId -Scopes $Scopes
$AccessToken = $Token.AccessToken
Get-JWTDetails -token $AccessToken



Note that under scp the "AdvancedHunting.Read" Permission is visible and also the UPN of the Account that has logged in.


The Query remains the same

#KQL Query Multiline
$query = @'
//TOP 10 URL Domains
EmailUrlInfo
| summarize count() by UrlDomain
| top 10 by count_
'@

$uri = "https://api.security.microsoft.com/api/advancedhunting/run"
$Headers = @{
    "Content-Type" = "application/json"
    "Authorization" = "Bearer "+ $AccessToken
    }
$Body = ConvertTo-Json -InputObject @{ 'Query' = $query }
$Response = Invoke-RestMethod -Method Post -Uri $uri -Headers $Headers -Body $Body
If ($Null -ne $Response)
{
    $Response.Results
}



And that's how you use PowerShell to Invoke KQL Querys in Microsoft 365 Defender Advanced Huniting.
Now it's your turn. Happy Hunting😊

Regards
Andres Bohren