Query Details

AzureHound Detection

Graph API Audit Events Azure Hound

Query

let WhitelistedObjects = dynamic(["obj1", "obj2"]);
let UniqueRequestThreshold = 1000; // Depends on Entra ID tentant size. You can use the function 0.5 * TotalAzure Resources to get this number. KQL: arg("").Resources | count
let ResourceThreshold = 4;
let ReconResources = dynamic(["organization","groups","devices","applications","users","rolemanagement","serviceprincipals"]);
GraphAPIAuditEvents
| where RequestMethod == "GET"
| where ResponseStatusCode == 200
| extend ParsedUri = tostring(parse_url(RequestUri).Path)
| extend GraphAPIPath = tolower(replace_string(ParsedUri, "//", "/"))
| extend GraphAPIResource = tostring(split(GraphAPIPath, "/")[2])
| where GraphAPIResource in (ReconResources)
// Filter whitelist
| where not(AccountObjectId in (WhitelistedObjects))
| summarize UniqueRequests = dcount(ClientRequestId), Requests = make_set(RequestUri, 1000), Paths = make_set(GraphAPIPath), Resources = make_set(GraphAPIResource), UniqueResourceCount = dcount(GraphAPIResource) by AccountObjectId, bin(TimeGenerated, 1h)
| where UniqueRequests >= UniqueRequestThreshold and UniqueResourceCount >= ResourceThreshold

About this query

Explanation

This query is designed to detect potential AzureHound activity within an Azure environment by analyzing Microsoft Graph API activity logs. AzureHound is a tool used by attackers to gather information about Azure tenants. Here's a simplified breakdown of what the query does:

  1. Data Source: It uses the GraphAPIAuditEvents table, which contains logs of activities performed via the Microsoft Graph API.

  2. Filtering Criteria:

    • It looks for GET requests with a successful response status code of 200, as AzureHound uses these to collect data.
    • It focuses on specific resources of interest, such as "organization", "groups", "devices", "applications", "users", "rolemanagement", and "serviceprincipals".
    • It excludes any requests made by accounts listed in a predefined whitelist (WhitelistedObjects).
  3. Analysis:

    • It counts the number of unique requests and the number of different resources accessed within one-hour timeframes.
    • It collects details about the requests, such as the request URIs and the paths accessed.
  4. Thresholds:

    • It checks if the number of unique requests exceeds a certain threshold (UniqueRequestThreshold), which can be adjusted based on the size of the Azure tenant.
    • It also checks if the number of different resources accessed exceeds a set threshold (ResourceThreshold).
  5. Output:

    • If both thresholds are exceeded, the query returns the results for further analysis, indicating potential AzureHound activity.

In summary, this query helps identify suspicious activity that could indicate an adversary is using AzureHound to gather information about your Azure environment.

Details

Bert-Jan Pals profile picture

Bert-Jan Pals

Released: November 1, 2025

Tables

GraphAPIAuditEvents

Keywords

MicrosoftGraphActivityLogsAzureHoundAzureTenantEntraIDOrganizationGroupsDevicesApplicationsUsersRolemanagementServiceprincipalsGraphAPIAuditEventsRequestMethodResponseStatusCodeRequestUriGraphAPIPathGraphAPIResourceAccountObjectIdClientRequestIdTimeGenerated

Operators

letdynamicargcountGraphAPIAuditEventswhereextendtostringparse_urlPathtolowerreplace_stringsplitinsummarizedcountmake_setbin

Actions

GitHub