Query Details

HUNT 16 First Seen Resource Provider Per Identity

Query

// Hunt     : Hunt - First-Seen Azure Resource Provider per Identity (30d)
// Tactics  : Discovery, Persistence
// MITRE    : T1078, T1580
// Purpose  : Flags identities invoking an Azure Resource Provider (e.g. Microsoft.Compute,
//            Microsoft.KeyVault) for the FIRST time in 30 days. A compromised identity that
//            suddenly touches a provider it has never used is a strong lateral-movement /
//            discovery signal. Pairs with RULE-09 (new IP) and RULE-12 (mass creation).
//==========================================================================================

let Window = 30d;
let Recent = 1d;
let Baseline = AzureActivity
    | where TimeGenerated between (ago(Window) .. ago(Recent))
    | where isnotempty(Caller) and isnotempty(OperationNameValue)
    | extend ResourceProvider = tostring(split(OperationNameValue, '/')[0])
    | summarize PriorProviders = make_set(ResourceProvider, 1000) by Caller;
AzureActivity
| where TimeGenerated > ago(Recent)
| where isnotempty(Caller) and isnotempty(OperationNameValue)
| extend ResourceProvider = tostring(split(OperationNameValue, '/')[0])
| join kind=leftouter Baseline on Caller
| where isempty(PriorProviders) or not(set_has_element(PriorProviders, ResourceProvider))
| summarize FirstSeen = min(TimeGenerated), Ops = count(),
    Providers = make_set(ResourceProvider, 10), IPs = make_set(CallerIpAddress, 10)
    by Caller
| order by FirstSeen desc

Explanation

This KQL (Kusto Query Language) query is designed to identify and flag any identities (users or service accounts) that are interacting with an Azure Resource Provider for the first time in the past 30 days. Here's a simple breakdown of what the query does:

  1. Time Frame: The query looks at Azure activity logs over a 30-day window, excluding the most recent day.

  2. Baseline Creation: It first establishes a baseline of which Azure Resource Providers each identity has interacted with over the past 29 days (excluding the most recent day). This is done by summarizing the resource providers accessed by each caller (identity).

  3. Current Activity: It then examines the Azure activity logs from the most recent day to see which resource providers are being accessed.

  4. Comparison: The query compares the current day's activity against the baseline. It identifies any resource providers that an identity is accessing for the first time in the 30-day window.

  5. Output: For each identity that accesses a new resource provider, the query outputs:

    • The first time this new provider was accessed.
    • The number of operations performed.
    • A list of new resource providers accessed.
    • A list of IP addresses from which the operations were performed.
  6. Purpose: This is useful for detecting potential security threats, such as compromised identities engaging in unusual behavior, which could indicate lateral movement or discovery tactics by an attacker.

The query is part of a broader security monitoring strategy, complementing other rules that detect new IP addresses or mass resource creation activities.

Details

David Alonso profile picture

David Alonso

Released: July 27, 2026

Tables

AzureActivity

Keywords

AzureResourceProviderIdentityCallerOperationNameValueTimeGeneratedIPAddress

Operators

letbetweenagowhereisnotemptyextendtostringsplitsummarizemake_setbyjoinkindisemptynotset_has_elementmincountorder bydesc

MITRE Techniques

Actions

GitHub