Files
entra-id-recon.py/README.md
GJRM dbd5b4d318 Update README.md
Changed some wording.
2026-03-12 18:47:01 +00:00

22 KiB

Entra-ID-Recon.py

Entra-ID-Recon.py is a Python script that reimplements some of the reconnaissance and user enumeration functionalities found within the AADInternals project. This script allows you to gather information about Entra-ID tenants and enumerate users to check their existence within an organisation, all from a Nix shell. You could use it on Windows as well, but this script becomes redundant in this context, because you can just use the original PowerShell code - seriously it has a lot more to offer:

Original source code and documentation

Credits

This script is inspired by the original AADInternals project created by Nestori Syynimaa (@DrAzureAD). All ideas and code belong to the original author, this script is a reimplementation of a very small subset of the original project and was created for educational purposes.

Disclaimer

  • This tool was created for the author's personal learning and for educational purposes, never run this script against an organisation in which you do not have explicit, written permission to conduct a legitimate security audit against.
  • Warning: the 'login' verification method will be detailed within the target tenant's Audit logs, tread carefully.

Features

Reconnaissance Capabilities

Based on AADInternals' Invoke-AADIntReconAsOutsider function - see documentation

  • Retrieve a target domain's tenant ID, company brand name, tenant region, and whether Seamless SSO is supported
  • Detect device code authentication support for the tenant
  • Check for SharePoint presence and Azure services
  • Discover all domains associated with the tenant via Autodiscover (managed domains)
  • Certificate Transparency domain discovery: Find additional active domains via CT logs (requires --ct flag) - Python implementation enhancement
  • MS Graph API domain discovery: Get complete domain information when authenticated (requires --graph-token) - Python implementation enhancement
  • Check DNS, MX, and SPF records for each domain
  • Identify federated vs managed domains
  • Check Azure provisioning endpoints (B2B, device registration, device management)
  • Progress bars for domain enumeration operations

User Enumeration Capabilities

  • Enumerate email addresses and validate whether they are active within the target organisation
  • Multiple enumeration methods:
    • GetCredentialType API (Primary method - stealthy)
    • OneDrive enumeration (Throttle-resistant, no authentication logs)
    • Autodiscover enumeration (Alternative method)
  • Support for combining multiple methods for verification
  • Automatic throttle detection and exponential backoff
  • Progress bars for long enumeration operations

OPSEC Features

  • Rate limiting: Configurable requests per second with burst capacity
  • User-Agent rotation: Random selection from multiple legitimate user agents
  • Randomised delays: 1-5 second delays between requests to avoid detection patterns
  • Session management: Connection pooling for efficiency
  • Throttle detection: Automatic detection and backoff when throttling is detected

Output Features

  • Save output in various formats: JSON, CSV, XLSX, and TXT are supported
  • Colour-coded output for better readability
  • Enhanced error handling and exception management
  • Integration of additional reconnaissance capabilities from msftrecon project

Requirements

  • Python 3.8 or higher
  • Required Python modules listed in requirements.txt.

Installation

  1. Clone this repository.
  2. Install the required Python modules:
    pip install -r requirements.txt
    

Usage

The script has two main functionalities: external recon and user enumeration. Below are the command-line options for each functionality.

External Recon - Retrieve information about an Entra-ID tenant.

This functionality is a Python reimplementation of AADInternals' Invoke-AADIntReconAsOutsider function. For the original PowerShell implementation and comprehensive documentation, refer to:

AADInternals Documentation: https://aadinternals.com/aadinternals/#invoke-aadintreconasoutsider

Relationship to AADInternals

The entra-external-recon command mirrors the functionality of Invoke-AADIntReconAsOutsider from the AADInternals PowerShell module. Both tools perform unauthenticated reconnaissance on Entra ID (Azure AD) tenants, gathering publicly available information including:

  • Tenant Information: Tenant ID, tenant name, tenant brand, tenant region
  • Domain Discovery: All verified domains associated with the tenant (managed and federated)
  • Domain Details: DNS records (MX, SPF), domain types (Managed/Federated), STS endpoints
  • SSO Status: Seamless Single Sign-On (Desktop SSO) enabled status
  • Authentication Methods: Device code authentication support
  • Service Detection: SharePoint presence, Azure services, provisioning endpoints

Key Differences:

  • This Python implementation adds Certificate Transparency (CT) log discovery (--ct flag) for finding additional active domains
  • This Python implementation adds MS Graph API integration (--graph-token flag) for cross-tenant domain discovery using findTenantInformationByTenantId
  • The original AADInternals function may have access to additional methods that leverage authenticated endpoints (marked with (A) in AADInternals documentation)

Note: As of recent Microsoft updates, some domain discovery methods have been restricted. The Autodiscover method may not return all domains (especially federated domains). The CT and Graph API methods in this script help compensate for these limitations.

Command:

python3 entra-id-recon.py entra-external-recon -d <domain> [-o <output_file>] [-e <extension>] [--ct] [--graph-token <token>]
Options:
  • -d, --domain: Domain name (example: example.com) [Required]
  • -o, --output: Output filename [Optional]
  • -e, --extension: Output format (choices: txt, json, csv, xlsx, all) [Optional] Note: the default format will be .txt if -e is not specified
  • --ct: Also check Certificate Transparency logs for additional active domains [Optional]
  • --graph-token: Access token for MS Graph API (optional, for authenticated domain discovery) [Optional]

Examples:

Basic usage
python3 entra-id-recon.py entra-external-recon -d example.com
Output to specific file and format
python3 entra-id-recon.py entra-external-recon -d example.com -o outputfile -e json
Output in all formats
python3 entra-id-recon.py entra-external-recon -d example.com -o outputfile -e all
Use Certificate Transparency for additional domain discovery
python3 entra-id-recon.py entra-external-recon -d example.com --ct
Automatic Domain Discovery (azmap.dev API)

The script automatically queries the azmap.dev API for domain discovery. This uses the same unauthenticated method that osint.aadinternals.com uses server-side. No additional flags needed:

python3 entra-id-recon.py entra-external-recon -d example.com

How It Works: The azmap.dev API uses an unauthenticated method that works cross-tenant. osint.aadinternals.com uses the same method but requires authentication only to prevent abuse - you can authenticate with ANY tenantand still query domains for other tenants (e.g., google.com) because the underlying method is unauthenticated.

Use MS Graph API with access token (for tenant metadata only)
# Get token using Azure CLI (device code flow for unaffiliated tenants)
az login --use-device-code

# Get token
TOKEN=$(az account get-access-token --resource https://graph.microsoft.com --query accessToken -o tsv)

# Use with script
python3 entra-id-recon.py entra-external-recon -d example.com --graph-token "$TOKEN"

Note: The Graph API endpoints (findTenantInformationByTenantId and findTenantInformationByDomainName) do NOT return domains, only basic tenant metadata (tenantId, displayName, defaultDomainName). Domain discovery is handled automatically via the azmap.dev API.

Combine Certificate Transparency and MS Graph API
TOKEN=$(az account get-access-token --resource https://graph.microsoft.com --query accessToken -o tsv)
python3 entra-id-recon.py entra-external-recon -d example.com --ct --graph-token "$TOKEN"

User Enumeration - Check the existence of users in an Entra-ID tenant.

Command:

python3 entra-id-recon.py entra-external-enum [-u <username>] [-o <output_file>] [-f <input_file>] [-e <extension>] [-m <method>] [--onedrive] [--autodiscover]
Options:
  • -u, --username: Username (example: user@example.com) [Optional]
  • -o, --output: Output filename without extension [Optional]
  • -f, --file: Input file with a list of email addresses [Optional]
  • -e, --extension: Output format (choices: txt, json, csv, xlsx, all) [Optional] Note: the default format will be .txt if -e is not specified
  • -m, --method: Login method (choices: normal, login, autologon) [Optional, default: normal]
  • --onedrive: Also use OneDrive enumeration method [Optional]
  • --autodiscover: Also use Autodiscover enumeration method [Optional]

Examples:

Check a single user
python3 entra-id-recon.py entra-external-enum -u user@example.com
Check multiple users
python3 entra-id-recon.py entra-external-enum -u "user1@example.com,user2@example.com"
Check users from an input file
python3 entra-id-recon.py entra-external-enum -f user-list.txt
Output results to a specific file and format
python3 entra-id-recon.py entra-external-enum -u user@example.com -o outputfile -e json
Use the login method for enumeration
python3 entra-id-recon.py entra-external-enum -u user@example.com -m login
Use OneDrive enumeration method (stealthy, no auth logs)
python3 entra-id-recon.py entra-external-enum -u user@example.com --onedrive
Combine multiple enumeration methods
python3 entra-id-recon.py entra-external-enum -f users.txt --onedrive --autodiscover

Output Information

External Reconnaissance Output

The reconnaissance command provides the following information:

  • Tenant ID: Unique identifier for the Entra ID tenant
  • Tenant Name: Domain name associated with the tenant
  • Tenant Brand: Federation brand name (if configured)
  • Tenant Region: Geographic region scope (Commercial, GCC, GCC-High, DoD, etc.)
  • Desktop SSO Enabled: Whether Seamless Single Sign-On is enabled
  • Device Code Auth: Whether device code authentication flow is supported
  • Domain Information: List of all domains associated with the tenant, including:
    • DNS resolution status
    • MX record presence
    • SPF record presence
    • Identity type (Managed/Federated)
    • STS endpoint (for federated domains)
    • Source indicator (Autodiscover, CT, or Graph API)
  • SharePoint Detection: Whether SharePoint is accessible for the tenant
  • Azure Services: Information about accessible Azure services including:
    • App Services
    • B2B invite endpoints
    • Device registration endpoints
    • Device management endpoints
  • Certificate Transparency Domains: Additional domains discovered via CT logs (when --ct is used)
  • MS Graph API Information: Complete tenant and domain information (when --graph-token is used)

User Enumeration Output

The enumeration command provides:

  • Username: The email address tested
  • Exists: Boolean indicating whether the user exists in the tenant
  • Method: The enumeration method(s) used
  • Additional Info: Additional information such as throttle status, OneDrive/Autodiscover results

Domain Discovery Methods

Autodiscover GetFederationInformation (Default)

  • Status: Partially functional (Microsoft changed behaviour in 2024)
  • Limitations: Only returns managed domains, no longer returns federated domains
  • Use Case: Primary method for discovering managed domains

Certificate Transparency Logs (--ct flag)

  • Status: Fully functional
  • Method: Queries crt.sh for SSL/TLS certificates
  • Filtering:
    • Only includes certificates expiring in current year or future (not expired)
    • Verifies domains are active (HTTP 200/301/302/401/403 responses)
    • Filters out obvious infrastructure subdomains
  • Advantages:
    • No authentication required
    • Can discover domains not returned by Autodiscover
    • Public data source
  • Limitations:
    • May include unrelated domains with similar names
    • Requires manual verification of results
    • Slower than Autodiscover method
  • Use Case: Additional domain discovery when Autodiscover is limited

azmap.dev API (Automatic)

  • Status: Fully functional (unauthenticated method)
  • Method: Uses the same unauthenticated method discovered after Microsoft patched Autodiscover
  • Reference: Sprocket Security Blog - Tenant Enumeration is Back
  • How It Works:
    • Uses an unauthenticated method that works cross-tenant
    • osint.aadinternals.com uses the same underlying method - it requires authentication only to prevent abuse/rate limiting, not because the method itself requires authentication
    • You can authenticate to osint.aadinternals.com with ANY tenant and still query domains for other tenants (e.g., google.com) because the underlying method is unauthenticated
    • azmap.dev provides the same functionality without requiring authentication
  • Advantages:
    • No authentication required (unlike osint.aadinternals.com which requires login for abuse prevention)
    • Returns all email domains for the target tenant
    • Works cross-tenant (can query any tenant's domains)
    • Free API (100,000 requests/day on Cloudflare's free tier)
  • Limitations:
    • Depends on azmap.dev API availability
    • Subject to rate limiting (429 responses)
    • May change if Microsoft patches the underlying method
  • Use Case: Primary method for unauthenticated domain discovery (automatically used by script)

MS Graph API (--graph-token flag)

  • Status: Functional but limited (requires authentication)
  • Method: Uses Microsoft Graph API findTenantInformationByTenantId and findTenantInformationByDomainName endpoints
  • Important Note:
    • These endpoints do NOT return domains, only basic tenant metadata (tenantId, displayName, defaultDomainName)
    • They are used for tenant information only, not domain discovery
  • Cross-Tenant Capability:
    • You can authenticate with your own tenant and query information about another tenant
    • However, this only returns basic tenant info, not domains
  • Advantages:
    • Provides tenant metadata (display name, default domain)
    • Works cross-tenant for basic tenant information
  • Limitations:
    • Requires authentication (access token)
    • Requires CrossTenantInformation.ReadBasic.All permission
    • Does NOT return domains (only basic tenant info)
  • Use Case: Getting basic tenant metadata when you have a Graph API token

Enumeration Methods

GetCredentialType API (Default)

  • Status: Fully functional
  • Stealth: High (no authentication logs)
  • Reliability: High
  • Throttling: Subject to rate limiting
  • Use Case: Primary enumeration method

OneDrive Enumeration

  • Status: Fully functional
  • Stealth: Very high (no authentication attempts logged)
  • Reliability: High
  • Throttling: Minimal observed throttling
  • Limitations: Only enumerates users with OneDrive provisioned
  • Use Case: Stealthy enumeration, throttle-resistant alternative

Autodiscover Enumeration

  • Status: Fully functional
  • Stealth: High (no authentication logs)
  • Reliability: Medium (may redirect for hybrid environments)
  • Throttling: Subject to rate limiting
  • Use Case: Verification and alternative method

OPSEC Considerations

The script implements several OPSEC features to reduce detection:

  1. Rate Limiting: Default 0.5 requests per second with randomised delays (1-5 seconds)
  2. User-Agent Rotation: Randomly selects from legitimate user agents
  3. Throttle Detection: Automatically detects throttling and implements exponential backoff
  4. Session Management: Uses connection pooling to appear more like legitimate traffic

Note: The 'login' and 'autologon' methods will generate sign-in log entries. Use the 'normal' method with OneDrive/Autodiscover for maximum stealth.

Obtaining MS Graph API Access Token

To use the --graph-token option, you need to obtain an access token for Microsoft Graph API. The recommended method on macOS is using Azure CLI:

Step 1: Install Azure CLI (if not already installed)

brew install azure-cli

Step 2: Login to Azure CLI

az login --use-device-code

This will open a browser or provide a code to enter at https://microsoft.com/devicelogin

Step 3: Get Access Token

az account get-access-token --resource https://graph.microsoft.com --query accessToken -o tsv

Step 4: Use with Script

# Store token in variable
TOKEN=$(az account get-access-token --resource https://graph.microsoft.com --query accessToken -o tsv)

# Use with script
python3 entra-id-recon.py entra-external-recon -d example.com --graph-token "$TOKEN"

One-liner

python3 entra-id-recon.py entra-external-recon -d example.com --graph-token $(az account get-access-token --resource https://graph.microsoft.com --query accessToken -o tsv)

Important Limitations

Cross-Tenant Discovery: The script uses findTenantInformationByTenantId which supports cross-tenant queries. You can authenticate with your own tenant and query information about any other tenant. However:

  • The findTenantInformationByTenantId endpoint returns up to 20 domains per tenant (Microsoft limitation)
  • The /domains endpoint (queried as fallback) only returns domains for the authenticated user's tenant
  • For complete domain discovery, combine multiple methods: Autodiscover, CT logs (--ct), and Graph API (--graph-token)

Why osint.aadinternals.com works: The osint.aadinternals.com tool uses the same findTenantInformationByTenantId endpoint, which is why it can query any tenant when you authenticate with your own tenant. This script now replicates that functionality.

Token Permissions

The access token should have one of the following permissions:

  • Directory.Read.All (Application permission)
  • Domains.Read.All (Application permission)
  • CrossTenantInformation.ReadBasic.All (for findTenantInformationByTenantId)

For delegated permissions, the authenticated user must have appropriate roles in their tenant.

Technical Details and Further Reading

Reverse Engineering

Reverse engineering scripts and documentation for analyzing how azmap.dev discovers tenant domains have been moved to the reverse-engineering/ directory to keep the main project clean.

See reverse-engineering/README.md for details.

Changelog

Version 2.2

  • Added Certificate Transparency domain discovery (--ct flag)
    • Queries crt.sh for SSL/TLS certificates
    • Filters expired certificates (only current year or future)
    • Verifies domains are active (HTTP 200/301/302/401/403)
    • Marks CT-discovered domains in output
  • Added MS Graph API support (--graph-token flag)
    • Optional authenticated domain discovery
    • Uses findTenantInformationByTenantId for cross-tenant domain discovery (works even when authenticated from different tenant)
    • Also queries /domains endpoint as fallback (returns authenticated user's tenant domains)
    • Provides complete domain information including type and STS endpoints
    • Cross-tenant capability: Can query any tenant's information when authenticated with any valid token (matches osint.aadinternals.com functionality)
  • Added progress bars for domain enumeration operations
  • Enhanced error handling for unexpected responses and keyboard interrupts
  • Improved domain deduplication when using multiple discovery methods
  • Enhanced domain discovery capabilities
  • Improved output formatting for multiple discovery methods

Version 2.1

  • Added OPSEC features: rate limiting, user-agent rotation, randomised delays
  • Added progress bars (tqdm) for user enumeration
  • Added OneDrive enumeration method
  • Added Autodiscover enumeration method
  • Added throttle detection and automatic backoff
  • Enhanced colour output throughout
  • Added session management for connection pooling
  • Integrated additional msftrecon capabilities (provisioning endpoints, Azure services)
  • Improved error handling and exception management

Version 2.0

  • Added device code authentication support detection
  • Integrated additional Azure services reconnaissance
  • Enhanced error handling and exception management
  • Fixed JSON output formatting issues
  • Added SharePoint detection
  • Improved British English spelling throughout
  • Enhanced output formatting and data structures