Entra Graph directory enumeration

Severity mediumCloud & SaaSThresholdstablecloud.identity.entra_graph_directory_enumeration · v1.0.0

Repeated Microsoft Graph reads of directory objects from one identity — the shape of a tenant being enumerated rather than used.

What it detects

Repeated Microsoft Graph reads of directory objects from one identity — the shape of a tenant being enumerated rather than used.

Directory enumeration leaves NO audit-log entry at all: reading Entra ID is not a change, so tools that map a tenant's users, groups, service principals, owners and role assignments to find an attack path (AzureHound, ROADrecon and friends) are invisible everywhere except Graph activity logs. What distinguishes them from an application doing its job is volume and breadth against directory endpoints in a short window, which is what this rule counts.

MITRE ATT&CK mapping

  • T1087.004Account Discovery: Cloud Account· Discovery
  • T1069.003Permission Groups Discovery: Cloud Groups· Discovery

False positives and triage

Identity governance, HR sync, SIEM collectors and IAM tooling read these same endpoints constantly and will cross this threshold every run — baseline the app registrations that legitimately do so and treat them as expected. The signal is enumeration from an INTERACTIVE user identity rather than a service principal, from an IP the tenant does not normally serve, or paging with $top=999 across object types the caller has no functional reason to read. Note this counts reads and so measures reconnaissance, not compromise; pair it with what the identity did next.

The rule

Declarative YAML read by the detection engine — data, never executed. Confidence 60%. Source: rules/cloud/entra_graph_directory_enumeration.yaml, licensed under the Apache License 2.0.

id: cloud.identity.entra_graph_directory_enumeration
version: 1.0.0
status: stable
severity: medium
confidence: 0.6
platforms: [application]
mitre_techniques: [T1087.004, T1069.003]
description: |
  Repeated Microsoft Graph reads of directory objects from one identity — the shape
  of a tenant being enumerated rather than used.

  Directory enumeration leaves NO audit-log entry at all: reading Entra ID is not a
  change, so tools that map a tenant's users, groups, service principals, owners and
  role assignments to find an attack path (AzureHound, ROADrecon and friends) are
  invisible everywhere except Graph activity logs. What distinguishes them from an
  application doing its job is volume and breadth against directory endpoints in a
  short window, which is what this rule counts.
match:
  provider: MicrosoftGraph
  url_path_contains_any:
    - "/servicePrincipals"
    - "/directoryRoles"
    - "/roleManagement"
    - "/groups"
    - "/users"
    - "/applications"
    - "/devices"
threshold:
  count: 10
  window_seconds: 600
  group_by: [user_name]
correlation_keys: [user_name]
false_positive_guidance: |
  Identity governance, HR sync, SIEM collectors and IAM tooling read these same
  endpoints constantly and will cross this threshold every run — baseline the app
  registrations that legitimately do so and treat them as expected. The signal is
  enumeration from an INTERACTIVE user identity rather than a service principal,
  from an IP the tenant does not normally serve, or paging with `$top=999` across
  object types the caller has no functional reason to read. Note this counts reads
  and so measures reconnaissance, not compromise; pair it with what the identity did
  next.

Related detections

Run this rule on your own logs — offline

KIROSEC runs this rule and the rest of the library over Windows, Linux, macOS and cloud audit logs on the analyst's own machine. Every alert links to the events that raised it, and nothing leaves the device.

Browse all detections