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.

I’ve published some of the KQL Querys in my GitHub Repo

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.

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

https://github.com/BohrenAn/GitHub_PowerShellScripts/blob/main/ExchangeOnline/EOPAdvancedHunting/AdvancedHuntingWithPS.ps1

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