Unauthenticated reconnaissance is the first step in assessing an Azure AD environment. This phase involves gathering information about the target organization's Azure presence without requiring any authentication credentials. The goal is to identify valid domains, user accounts, and potential entry points that can be leveraged in subsequent phases of an engagement.
Practice
Check if Company is Using Azure AD
Before starting any Azure AD enumeration, it's important to verify if the target company is actually using Azure AD. This can be done through various methods.
If the NameSpaceType indicates "Managed", then the company is using Azure AD.
if the NameSpaceType indicates "Federated", then the company is using Active Directory Federation Services (AD FS) .
# Replace <DOMAIN> with the actual target FQDN
curl -s "https://login.microsoftonline.com/getuserrealm.srf?login=username@<DOMAIN>&json=1" | jq
Using AADInternals (Powershell), If the Account Type indicates "Managed", then the company is using Azure AD.
Tenant enumeration involves gathering information about the Azure AD tenant configuration, including domain names, authentication methods, and tenant-specific details. This information can be obtained through various public APIs and tools.
TenantID
We can retreive the Tenant ID by quering the OpenID Configuration API endpoint
We can retreive the Tenant ID using AADInternals (Powershell).
Get-AADIntTenantID -Domain <DOMAIN>
Domains
We can enumerate additional domains using AADInternals (Powershell).
Get-AADIntTenantDomains -Domain <DOMAIN>
Services Enumeration
Organizations often use various Azure services that can be discovered through DNS enumeration or by checking common Azure subdomains.
Enumerate Azure SubDomains
It's possible to try to find Azure services exposed in common azure subdomains like the ones documented in this post.
MicroBurst (Powershell) can be used to achieve that goal, and enumerate Azure Subdomains.
# This script takes a base word and a list of permutations and enumerates several Azure services for potential targets.
# Base: The base word to use
# Permutations: A path to a permutation wordlist
Invoke-EnumerateAzureSubDomains -Base company -Permutations ".\permutations.txt" -Verbose
Azure Storage Account are Microsoft's cloud storage solution, similar to Amazon S3. It includes several services like the Blob storage, for unstructured data (images, videos, and documents..).
Anonymous read access may be enabled by a public access policies for blobs. Furthermore, storage resources follow predictable URL patterns at core.windows.net:
storage-account-name.blob.core.windows.net
storage-account-name.file.core.windows.net
storage-account-name.table.core.windows.net
storage-account-name.queue.core.windows.net
MicroBurst (Powershell) can then be used to brute-force storage account names, containers, and files (blobs):
# This script takes a base word and prefixes/suffixes it with a list of words to identify any storage blobs associated with a target.
# It will also attempt to enumerate any containers in the blob.
## Base: The base word to use
## OutputFile: Where to save the results
## Permutations: A path to a permutation wordlist (default is Microburst/Misc/permutations.txt)
Invoke-EnumerateAzureBlobs -Base company -Permutations ".\permutations.txt" -OutputFile azureblobs.txt
SAS URLs
A shared access signature (SAS) URL is an URL that provides access to certain part of a Storage account (could be a full container, a file...) with some specific permissions (read, write...) over the resources. If you find one leaked you could be able to access sensitive information, they look like this (this is to access a container, if it was just granting access to a file the path of the URL will also contain that file):
By default, access to pull or push images from an Azure Container Registry is only available to authenticated users. But it's possible to allow anonymous pull access.
Authorizing anonymous pulls can be done as follows (need permissions)
az acr update --name <registry-name> --anonymous-pull-enabled true
If we know such registry name and images, we can pull it as follows
The GetCredentialType API can be used for username enumeration.
Ensure that the domain is managed (refer to this section) to guarantee accurate results when using this technique. If it doesn't, unmanaged domains can return 0, leading to false positives
# Return values:
#0 The account exists, and uses that domain for authentication
#1 The account doesnโt exist
#2 The response is being throttled
#4 Some server error
#5 The account exists, but is set up to authenticate with a different identity provider. This could indicate the account is only used as a personal account
#6 The account exists, and is set up to use both the domain and a different identity provider
curl -s -X POST https:///login.microsoftonline.com/common/GetCredentialType --data '{"Username":"user1@example.com"}' | jq '.IfExistsResult'
o365spray (python) is a username enumeration and password spraying tool aimed at Microsoft Office 365 (O365). It can be used to validate users trough various methods: autologon, oauth2, office, onedrive, rst
The onedrive module relies on the target user(s) having previously logged into OneDrive. If a valid user has not yet used OneDrive, their account will show as 'invalid'.
o365creeper (Python) is a script that performs email address validation against Office 365 without submitting login attempts. It use the GetCredentialType API and check for the IfExistsResult field.
# Test a single email address
o365creeper.py -e test@example.com
# Test a list of email addresses
o365creeper.py -f potential-emails.txt
# Test a list of email addresses and save to file
o365creeper.py -f potential-emails.txt -o valid-emails.txt
onedrive_user_enum (Python) can be used to validate O365 users trough the OneDrive API.
# -t: tenant name
# -d: target domain name (required)
# -U: file containing usernames (wordlists)
# -u: single user to target
python onedrive_enum.py -t microsoft -d microsoft.com -U potential-users.txt
We can check if a user exists in a tenant using AADInternals (Powershell).
# Using a single email address
Invoke-AADIntUserEnumerationAsOutsider -UserName "user@company.com"
# Using a list of email addresses
Get-Content .\potential-emails.txt | Invoke-AADIntUserEnumerationAsOutsider