Advanced Hunting with the M365 Defender API

This blog describes how to use the Microsoft 365 Defender API to programmatically run advanced hunting queries in PowerShell and includes working code. The Microsoft 365 Defender API can be confusing to many people and creating a script such as the one described in this blog is often difficult to do without a proper understanding of the M365 Defender API, but I will aim to make this guide very straight forward and simple.

Registering an Azure AD Application

In order to use the M365 Defender API with application context (as opposed to user context), we must first register an application in Azure AD. The Microsoft document below describes how to do this:

Create an app to access Microsoft 365 Defender without a user | Microsoft Docs

This blog will follow the same steps provided in the documentation above, however I will describe how to set this up with the appropriate permissions needed to run advanced hunting queries not only for Microsoft Defender for Endpoint (MDE), but also for the other M365 Defender products such as Defender for Office (MDO) and Defender for Identity (MDI).

  1. Sign into Azure as a user with Global Administrator role.
  2. Navigate to Azure Active Directory > App registrations > New registration.
  3. Create a name for your application, then select Register
  4. Now on your application page, select API Permissions > Add permission > APIs my organization uses > then type Microsoft Threat Protection and select Microsoft Threat Protection.
  5. Check the box for AdvancedHunting.Read.All then select Add permissions.
  6. Select Grant admin consent. (Any time a new permission is added, you must grant admin consent for it to take effect.)
  7. Select Certificates & secrets, add a description to the secret, then select Add. Make sure to copy the secret value somewhere because you will need it for the PowerShell script.
  8. Lastly, you will want to copy your Application (client) ID and your Directory (tenant) ID. You can get these values by selecting Overview from your application page.

Getting an Access Token

In your advanced hunting PowerShell script, you will need to generate an access token using your tenant ID, client ID, and application secret from the last section. You will paste those values into the PowerShell code below.

$tenantId = '' # Paste your directory (tenant) ID between the quotes here
$appId = '' # Paste your application (client) ID between the quotes here
$appSecret = '' # Paste your own app secret between the quotes here to test, then store it in a safe place, such as the Azure Key Vault!

$resourceAppIdUri = 'https://api.security.microsoft.com'
$oAuthUri = "https://login.windows.net/$tenantId/oauth2/token"

$authBody = [Ordered] @{
    resource = $resourceAppIdUri
    client_id = $appId
    client_secret = $appSecret
    grant_type = 'client_credentials'
}
$authResponse = Invoke-RestMethod -Method Post -Uri $oAuthUri -Body $authBody -ErrorAction Stop
$token = $authResponse.access_token

Note that your access token is stored in a variable named $token. This is useful to know for troubleshooting purposes, especially if you plan to build out this script further to perform other activities using the Microsoft Defender for Endpoint API.

In the Microsoft document listed above, Microsoft provides this webpage: JSON web token validator website where you can paste your access token value and see all the “roles” or permissions it has assigned to it.

Adding the Advanced Hunting Query

This is where many people tend to make mistakes, because at the time of writing this, there exists two separate APIs for Advanced Hunting queries. One API is only capable of running advanced hunting queries against Microsoft Defender for Endpoint (MDE) tables and will not be able to query Defender for Identity or Defender for Office tables such as EmailEvents.

In order to query all tables in the M365 Defender product suite, we will need to use the M365 Defender API. These two similar APIs will require different application permissions and will yield different results. Therefore, you will want to use the M365 Defender API in order to query all advanced hunting tables available.

The MDE API for advanced hunting is described here: Advanced Hunting API | Microsoft Docs

The M365 API for advanced hunting is described here: Microsoft 365 Defender advanced hunting API | Microsoft Docs

To complete the script, insert the following PowerShell code underneath the code provided above to run advanced hunting queries in your M365 Defender tenant.

$resourceAppIdUri = 'https://api.security.microsoft.com'
    $oAuthUri = "https://login.microsoftonline.com/$TenantId/oauth2/token"
    $authBody = [Ordered] @{
    resource = "$resourceAppIdUri"
    client_id = "$appId"
    client_secret = "$appSecret"
    grant_type = 'client_credentials'
}
    $authResponse = Invoke-RestMethod -Method Post -Uri $oAuthUri -Body $authBody -ErrorAction Stop
    $token = $authResponse.access_token

    Write-Host "Paste your Advanced Hunting Query here:"
    $query = Read-Host  
    $url = "https://api.security.microsoft.com/api/advancedhunting/run" 
$headers = @{ 
    'Content-Type' = 'application/json'
    Accept = 'application/json'
    Authorization = "Bearer $token" 
}
$body = ConvertTo-Json -InputObject @{ "Query" = $query}
$webResponse = Invoke-WebRequest -Method Post -Uri $url -Headers $headers -Body $body -ErrorAction Stop -UseBasicParsing
$response =  $webResponse | ConvertFrom-Json
$results = $response.Results

Write-Host "`r`n"
$OutputSelection = Read-Host "Would you like to output to a file? (y/n)" 
switch ($OutputSelection)
{
'y' {
$ahOutputFilePath = Read-Host "Enter file name and full path. Must be a CSV file."
$results | ConvertTo-Csv -NoTypeInformation | Set-Content $ahOutputFilePath -Force}

'n' {$results}
}

Note that this code will prompt the user to paste an advanced hunting query to run and will ask if you would like to output the results to a .CSV file or if you would like the results outputted in the PowerShell console.

I would even recommend creating a menu that contains premade advanced hunting queries to choose from by replacing the value of the $query variable. If you need any ideas for premade queries, check out this blog:

https://laboccupied.wordpress.com/5-powerful-advanced-hunting-queries/


For now, I’ll leave the rest to your imagination. Thanks for reading!

One thought on “Advanced Hunting with the M365 Defender API

Leave a comment