Date
December 10, 2025
Author
Karan Patel
,
CEO

Microsoft Entra ID (formerly Azure Active Directory) is the backbone of identity management for thousands of enterprises running on Microsoft 365 and Azure. When an attacker or red teamer gains initial access to an Entra ID environment, one of the first phases they undertake is enumeration. Understanding what is in the tenant, who has access to what, and how service identities are configured can unlock the path to privilege escalation, lateral movement, and data exfiltration.

This blog walks through how Entra ID enumeration works across four key objects: users, groups, applications, and service principals. Whether you are a defender who wants to understand attacker tradecraft or a security professional testing your own environment, this guide gives you the commands, context, and clarity to work effectively.

If your organization needs a thorough assessment of its Entra ID attack surface, Redfox Cybersecurity offers specialized cloud pentesting services that cover exactly this threat area.

What Is Entra ID Enumeration and Why Does It Matter

Enumeration is the process of systematically querying a target environment to extract information about its objects, configurations, and relationships. In the context of Entra ID, this means pulling data from Microsoft Graph API, Azure CLI, PowerShell modules, and third-party tooling to map out the tenant.

Attackers use enumeration to answer critical questions: Which users exist? Which accounts have admin roles? What applications are registered? Which service principals carry sensitive permissions? Defenders need to understand this process to detect it, control what is exposed, and harden their tenant against abuse.

Entra ID is particularly interesting because much of its data is accessible to any authenticated user by default. A low-privilege account with no special roles can often enumerate users, groups, and applications across the entire tenant, which is a significant attack surface that is frequently underestimated.

Setting Up Your Enumeration Toolkit

Before diving into object-specific enumeration, you need the right tools in place. The most commonly used tools for Entra ID enumeration are:

  • Microsoft Graph PowerShell SDK
  • Azure CLI (az)
  • AADInternals (open-source PowerShell module by Dr. Nestori Syynimaa)
  • ROADrecon (Python-based Azure AD reconnaissance tool)
  • BloodHound with AzureHound (for relationship mapping)

Installing and Connecting

Microsoft Graph PowerShell:

Install-Module Microsoft.Graph -Scope CurrentUser
Connect-MgGraph -Scopes "User.Read.All","Group.Read.All","Application.Read.All","Directory.Read.All"

[cta]

Azure CLI:

az login
az account set --subscription "<subscription-id>"

AADInternals:

Install-Module AADInternals
Import-Module AADInternals
Get-AADIntLoginInformation -UserName "user@targetdomain.com"

[cta]

ROADrecon:

pip install roadrecon
roadrecon auth -u user@targetdomain.com -p Password123
roadrecon gather
roadrecon gui

[cta]

Once authenticated, you are ready to begin enumerating the four key object types.

Enumerating Entra ID Users

Users are the most common enumeration target. Attackers look for high-value accounts such as Global Administrators, service accounts, guest users, and accounts with password policies that may be weaker.

Listing All Users

Via Microsoft Graph PowerShell:

Get-MgUser -All | Select-Object DisplayName, UserPrincipalName, AccountEnabled, JobTitle, Department

[cta]

Via Azure CLI:

az ad user list --output table

[cta]

Via MS Graph API (curl):

curl -H "Authorization: Bearer <access_token>" \
 "https://graph.microsoft.com/v1.0/users?$select=displayName,userPrincipalName,accountEnabled,assignedLicenses"

[cta]

Finding Privileged Users

One of the first things an attacker does is identify who holds directory roles. Global Administrators, Privileged Role Administrators, and Application Administrators are the crown jewels.

# Get all role assignments
Get-MgDirectoryRole | ForEach-Object {
   $role = $_
   Get-MgDirectoryRoleMember -DirectoryRoleId $role.Id | ForEach-Object {
       [PSCustomObject]@{
           Role = $role.DisplayName
           Member = $_.AdditionalProperties["displayName"]
           UPN = $_.AdditionalProperties["userPrincipalName"]
       }
   }
}

[cta]

Identifying Guest Users

Guest accounts (B2B users) often have fewer restrictions and can be a vector for privilege abuse or phishing.

Get-MgUser -Filter "userType eq 'Guest'" -All | Select-Object DisplayName, UserPrincipalName, Mail

[cta]

Pre-Authentication Enumeration

Before even authenticating, attackers can validate whether a username exists in a tenant using the GetCredentialType endpoint.

curl -s -X POST "https://login.microsoftonline.com/common/GetCredentialType" \
 -H "Content-Type: application/json" \
 -d '{"Username":"target@company.com"}' | python3 -m json.tool

[cta]

A "ThrottleStatus": 0 and "IfExistsResult": 0 in the response indicates the user exists.

This type of unauthenticated reconnaissance is something Redfox Cybersecurity's red team evaluates during external cloud attack simulations. If your tenant is leaking user existence data to unauthenticated requests, it is worth knowing before attackers find out first.

Enumerating Entra ID Groups

Groups control access to resources, applications, and roles. Enumerating groups reveals which users have access to sensitive resources and which groups are used for role-assignable access.

Listing All Groups

Get-MgGroup -All | Select-Object DisplayName, GroupTypes, SecurityEnabled, MailEnabled, IsAssignableToRole
az ad group list --output table

[cta]

Finding Role-Assignable Groups

Role-assignable groups are high-value targets because any member of such a group inherits a directory role.

Get-MgGroup -Filter "isAssignableToRole eq true" -All | Select-Object DisplayName, Id

[cta]

Listing Members of a Specific Group

$groupId = "<group-object-id>"
Get-MgGroupMember -GroupId $groupId | ForEach-Object {
   $_.AdditionalProperties["displayName"]
}

[cta]

Finding Nested Group Memberships

Nested groups are frequently overlooked in access reviews. A user may be a member of a low-privilege group that is itself a member of a high-privilege group.

Get-MgUserMemberOf -UserId "<user-object-id>" -All | Select-Object -ExpandProperty AdditionalProperties | ForEach-Object { $_["displayName"] }

[cta]

Dynamic Groups

Dynamic groups automatically add members based on user attributes. If an attacker can modify a user's attributes (e.g., department, jobTitle), they may be able to add themselves to privileged dynamic groups.

Get-MgGroup -Filter "groupTypes/any(c:c eq 'DynamicMembership')" -All | Select-Object DisplayName, MembershipRule

[cta]

Enumerating Entra ID Applications

App registrations in Entra ID represent custom applications that have been granted permissions to Microsoft Graph and other APIs. Misconfigured apps are a frequent source of privilege escalation during pentests.

Listing All App Registrations

Get-MgApplication -All | Select-Object DisplayName, AppId, SignInAudience, PublisherDomain
az ad app list --output table

[cta]

Identifying Apps with High Permissions

Apps granted Application permissions (not Delegated) to Microsoft Graph can act without user interaction, making them powerful abuse targets.

Get-MgApplication -All | ForEach-Object {
   $app = $_
   Get-MgApplicationRequiredResourceAccess -ApplicationId $app.Id | ForEach-Object {
       [PSCustomObject]@{
           App = $app.DisplayName
           AppId = $app.AppId
           ResourceAppId = $_.ResourceAppId
           Permissions = ($_.ResourceAccess | ForEach-Object { $_.Id }) -join ", "
       }
   }
}

[cta]

Finding Apps with Credentials (Secrets and Certificates)

Apps with client secrets or certificates can authenticate independently. If these credentials are exposed, they become a major entry point.

Get-MgApplication -All | Where-Object { $_.PasswordCredentials -or $_.KeyCredentials } | Select-Object DisplayName, AppId, PasswordCredentials, KeyCredentials

[cta]

Apps Accessible by External Users

Multi-tenant apps and apps with SignInAudience set to AzureADMultipleOrgs or AzureADandPersonalMicrosoftAccount are reachable from outside the tenant.

Get-MgApplication -Filter "signInAudience ne 'AzureADMyOrg'" -All | Select-Object DisplayName, AppId, SignInAudience

[cta]

Application misconfigurations are among the most commonly exploited weaknesses in cloud environments. Redfox Cybersecurity's cloud security assessments routinely uncover over-permissioned app registrations that give attackers a direct path to sensitive data.

Enumerating Service Principals

Service principals are the runtime identity of an application within a specific tenant. They are the objects that actually hold permissions, role assignments, and credentials. While app registrations define the app globally, service principals define how that app behaves inside your tenant.

Listing All Service Principals

Get-MgServicePrincipal -All | Select-Object DisplayName, AppId, ServicePrincipalType, AccountEnabled
az ad sp list --output table

[cta]

Identifying Managed Identities

Managed identities are a special type of service principal. System-assigned managed identities are tied to a specific Azure resource (such as a VM or function app), while user-assigned identities can be attached to multiple resources. If an attacker compromises a resource with a managed identity, they inherit all permissions assigned to that identity.

Get-MgServicePrincipal -Filter "servicePrincipalType eq 'ManagedIdentity'" -All | Select-Object DisplayName, AppId, Id

Finding Service Principals with Privileged Roles

Get-MgDirectoryRole | ForEach-Object {
   $role = $_
   Get-MgDirectoryRoleMember -DirectoryRoleId $role.Id | Where-Object {
       $_.AdditionalProperties["@odata.type"] -eq "#microsoft.graph.servicePrincipal"
   } | ForEach-Object {
       [PSCustomObject]@{
           Role = $role.DisplayName
           ServicePrincipal = $_.AdditionalProperties["displayName"]
           AppId = $_.AdditionalProperties["appId"]
       }
   }
}

[cta]

Listing OAuth2 Permission Grants

OAuth2 permission grants represent delegated permissions that a user has consented to on behalf of an application. Attackers look for grants that allow broad access to Graph resources.

Get-MgOauth2PermissionGrant -All | Select-Object ClientId, ConsentType, PrincipalId, Scope

[cta]

App Role Assignments to Service Principals

Application permissions (app roles) granted directly to a service principal are the most dangerous. These allow the service principal to call APIs without any user present.

Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId "<sp-object-id>" -All

[cta]

Using AzureHound for Relationship Mapping

AzureHound is the Azure collector for BloodHound. It maps all Entra ID objects and their relationships into a graph database, making it easy to identify attack paths that are invisible through manual enumeration.

# Install AzureHound
git clone https://github.com/BloodHoundAD/AzureHound.git
cd AzureHound

# Run collection
./azurehound -u "user@domain.com" -p "Password123" list --tenant "tenantid" -o output.json

# Import into BloodHound
# Upload output.json via BloodHound UI

[cta]

Once imported, you can run pre-built queries such as:

  • "Find all paths to Global Admin"
  • "Find Service Principals with high-privilege app roles"
  • "Find users with direct paths to sensitive applications"

This visual approach to enumeration is one reason why AzureHound has become a standard tool in red team engagements. If you want to see what an attacker sees in your environment, book a cloud penetration test with Redfox Cybersecurity.

Detection and Defense Considerations

Understanding enumeration from the attacker's perspective directly informs defensive measures.

Audit Log Monitoring: All Microsoft Graph API calls by non-interactive service principals should be monitored in the Entra ID sign-in and audit logs. Look for bulk user enumeration patterns, sudden spikes in directory read operations, and unusual app consent grants.

Restrict Default User Permissions: In Entra ID, the default setting allows any user to enumerate all other users. This can be restricted under External Identities and User Settings in the Entra ID portal.

Enable Conditional Access for Service Principals: Workload identity Conditional Access policies can restrict where and how service principals authenticate, adding a layer of control against stolen credentials.

Regular App and SP Audits: Unused app registrations with valid client secrets are a persistent risk. Quarterly reviews of all app registrations, their permissions, and their credential expiry dates should be standard practice.

Use Privileged Identity Management: PIM enforces just-in-time access for privileged roles, reducing the exposure window even if an account is compromised.

Wrapping Up

Entra ID enumeration is not a niche skill reserved for advanced attackers. Any authenticated user in a tenant can run most of the commands shown in this blog. The combination of permissive defaults, the richness of Microsoft Graph API, and the complexity of permission models means that even well-managed environments can have significant blind spots.

Red teams enumerate to find what defenders have missed. By understanding the exact techniques covered here, including user discovery, group relationship mapping, application permission analysis, and service principal abuse paths, security teams can build more targeted detection rules and close the gaps before they are exploited.

Redfox Cybersecurity specializes in cloud-focused adversarial testing across Microsoft Azure and Entra ID environments. From identifying over-permissioned service principals to mapping privilege escalation paths through BloodHound, the team brings real-world attacker methodology to your assessment. If you are ready to find out what an attacker would see in your tenant, engage Redfox Cybersecurity's pentesting services today.

Copy Code