Anonymous Azure Reconnaissance — Enumerating a tenant’s resources and users
I’ve put this together in an effort to collect my thoughts, notes and idea’s around relatively passive reconnaissance in Azure. With the goal to cover ‘attacks’ that do not require any authentication to an Azure tenant but will help you find what Azure services are being used or exposed. This is the first step you should take that may lead to an initial access point.
First — know that you do not need pre-approval to conduct a penetration test against Azure Services but you do for other Microsoft cloud services such as Office 365. Despite not needing approval for Azure however, there are still rules of engagement that must be complied with.
Finding Azure public IP address ranges
A public IP address (static or dynamic don’t forget) can be allocated to too many Azure resources to list here. As with any standard penetration test, you should attempt to discover resources that are available within an organization’s environment by scanning these IP addresses. But what if you don’t have your target’s IP address ranges?
If you have not been given an IP range, you can run the following commands from your target’s subscriptions, using Azure CLI:
az network public-ip list --query '[].[name, ipAddress, publicIpAllocationMethod]' -o table
Or by using the AZ PowerShell Module:
Get-AzPublicIpAddress | Select Name,IpAddress,PublicIpAllocationMethod
Of course, to remain anonymous — you can find relevant IP ranges via this JSON file that Microsoft updates each week for all Azure regions and public services. This is a great resource to find Azure targets using publicly available information. It’s also a useful way to determine whether your current target is an Azure resource or not by comparing it’s IP to the ranges published in this file.
Remember that the IPs you’re testing could be dynamic and may change! It might be worth targeting the DNS hostnames once you do have a confirmed IP, limiting the chance you scan newly out-of-scope IPs.
Enumerating Services with standardized DNS suffixes
When you make a resource, Azure assigns it a subdomain with the resource’s associated DNS suffix in the format of:
<resource instance name>.<service dns suffix name>
E.g the public DNS suffix of the Azure Blob storage service is ‘blob.core.windows.net’. If you create an instance of a storage account named Jacobs_Storage, the FQDN of that resource instance will be Jacobs_Storage.blob.core.windows.net.
Also important to note, some DNS suffixes can be regional while others global. Here is the comprehensive list of DNS suffixes Azure uses for their resources.
This standardized naming convention Azure implements is useful for DNS resolution and for brute-forcing / enumerating hostnames to discover active Azure resources.
You could create a comprehensive list of words associated with your target’s organization and iterate through these subdomains with a tool like MicroBurst — a tool great for Azure specific pen testing.
Notes: Some Azure services allow customers to use custom domains or some hosts may have redirects or transparent proxies in place to obfuscate the fact that services are hosted in Azure. Whether a target is in Azure or not will subtly influence how a pentest is conducted on a specific target so it’s important to determine what environment your target lives.
Finding the Tenant Domain Name
If you can get a hold of the tenant’s domain (‘tenantname.onmicrosoft.com’) there are a number of public API’s you can hit that can provide a lot more information. There are a few ways you can get the domain if you haven’t already.
- Email Header Analysis — If you have received an email from a user in the tenant, view the headers of the email and look for header fields like
Received:
which might include the sending server's domain, often reflecting the primary or custom domain used by the organization. - If you are OK with something a little noisey, attempt a login with a known email address associated with the tenant. This email address should have a format like
user@customdomain.com
. After entering the email, the login page might redirect to a tenant-specific login URL that includes the tenant domain. - If you have an application registered in Azure AD and can authenticate to it, you can use the Microsoft Graph API to retrieve tenant information. Use an endpoint like
/organization
to get details about the tenant, where the response might give you some more information:
GET https://graph.microsoft.com/v1.0/organization
- Never forget that there might be some public resources and documentation that you might come across as well with some trusty OSINT.
Tenant Enumeration
Once you have the tenant’s domain, there’s only one AADInternal command you really need to know —
Invoke-AADIntReconAsOutsider -DomainName corp.onmicrosoft.com | Format-Table
Which is described here as, “Starts tenant recon of the given domain. Gets all verified domains of the tenant and extracts information such as their type. Also checks whether Desktop SSO (aka Seamless SSO) is enabled for the tenant.” An example output looks like this:
Tenant brand: Company Ltd
Tenant name: company
Tenant id: 1937e3ab-38de-a735-a830-3075ea7e5b39
DesktopSSO enabled: True
Name DNS MX SPF Type STS
---- --- -- --- ---- ---
company.com True True True Federated sts.company.com
company.mail.onmicrosoft.com True True True Managed
company.onmicrosoft.com True True True Managed
int.company.com False False False Managed
User Enumeration
AADInternals is very useful here as well — to check if a user exists in a tenant, you can run this command:
# Check does the user exist
Invoke-AADIntUserEnumerationAsOutsider -UserName "user@company.com"
Like before, more information can be read on their GitHub here. Once you find a user, this AADInternals command will allow you to get more information about the user:
Get-AADIntLoginInformation -UserName root@corp.onmicrosoft.com
o365creeper is a similar tool to validate users:
o365creeper.py -e test@example.com
o365creeper.py -f emails.txt
o365creeper.py -f emails.txt -o validemails.txt
Lastly, you can enumerate users via Microsoft Teams with TeamsEnum which will also tell you the users current online status with this command:
python3 TeamsEnum.py -a password -u <username> -f inputlist.txt -o teamsenum-output.json
Which will produce an output like:
[-] user1@domain - Target user not found. Either the user does not exist, is not Teams-enrolled or is configured to not appear in search results (personal accounts only)
[+] user2@domain - User2 | Company (Away, Mobile)
[+] user3@domain - User3 | Company (Available, Desktop)
Conclusion
To quickly sum up all I have to say:
- Find Azure public IP address ranges with this Microsoft published JSON file.
- Azure standardizes DNS suffixes based on resource type. Brute-force these DNS suffixes with Microburst.
Once you have a tenant’s domain via some email header analysis or OSINT:
- Tenant enumeration can be done via AADInternals.
- User Enumeration can be done via AADInternals, o365creeper, or via TeamsEnum.
I’d like to reference HackTricks and ‘Penetration Testing Azure for Ethical Hackers’ by David Okeyode and Karl Fosaaen as the incredible resources I used to make the bulk of my notes.