# Unauthenticated Reconnaissance

## Theory

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.

{% tabs %}
{% tab title="Manually" %}
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) .

```bash
# Replace <DOMAIN> with the actual target FQDN
curl -s "https://login.microsoftonline.com/getuserrealm.srf?login=username@<DOMAIN>&json=1" | jq
```

{% endtab %}

{% tab title="AADInternals" %}
Using [AADInternals](https://github.com/Gerenios/AADInternals) (Powershell), If the `Account Type` indicates "Managed", then the company is using Azure AD.

```powershell
Get-AADIntLoginInformation -UserName user@<DOMAIN>
```

{% endtab %}
{% endtabs %}

### Tenant Enumeration

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.

{% tabs %}
{% tab title="Manually" %}

#### TenantID

We can retreive the Tenant ID by quering the OpenID Configuration API endpoint

```bash
curl -s https://login.microsoftonline.com/ocd-testing.com/.well-known/openid-configuration | jq .token_endpoint
```

#### Domains

We can enumerate additional domains associated with the tenant using the Autodiscover service:

```bash
domain="example.com";curl -s https://autodiscover-s.outlook.com/autodiscover/autodiscover.svc -H "Content-Type: text/xml" -d @- << EOF |xq
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:exm="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:ext="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Header>
    <a:Action soap:mustUnderstand="1">http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetFederationInformation</a:Action>
    <a:To soap:mustUnderstand="1">https://autodiscover-s.outlook.com/autodiscover/autodiscover.svc</a:To>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
  </soap:Header>
  <soap:Body>
    <GetFederationInformationRequestMessage xmlns="http://schemas.microsoft.com/exchange/2010/Autodiscover">
      <Request>
        <Domain>$domain</Domain>
      </Request>
    </GetFederationInformationRequestMessage>
  </soap:Body>
</soap:Envelope>
EOF
```

{% endtab %}

{% tab title="AADInternals" %}

#### All-In-One

We can query all the information of an Azure tenant with **just one command from** [AADInternals](https://github.com/Gerenios/AADInternals) (Powershell).

```powershell
Invoke-AADIntReconAsOutsider -DomainName company.com | Format-Table
```

#### TenantID

We can retreive the Tenant ID using [AADInternals](https://github.com/Gerenios/AADInternals) (Powershell).

```powershell
Get-AADIntTenantID -Domain <DOMAIN>
```

#### Domains

We can enumerate additional domains using [AADInternals](https://github.com/Gerenios/AADInternals) (Powershell).

```powershell
Get-AADIntTenantDomains -Domain <DOMAIN>
```

{% endtab %}
{% endtabs %}

### Services Enumeration

Organizations often use various Azure services that can be discovered through DNS enumeration or by checking common Azure subdomains.

<details>

<summary>Enumerate Azure SubDomains</summary>

It's possible to try to find **Azure services exposed** in common azure subdomains like the ones documented in this [post](https://www.netspi.com/blog/technical-blog/cloud-penetration-testing/enumerating-azure-services/).

[MicroBurst](https://github.com/NetSPI/MicroBurst) (Powershell) can be used to achieve that goal, and enumerate Azure Subdomains.

```powershell
# 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 
```

The same can be acheive using [cloud\_enum](https://github.com/initstring/cloud_enum/tree/master) (python)

```bash
python cloud_enum.py -k target.com --disable-aws --disable-gcp
```

</details>

<details>

<summary>Enumerate Azure Storage Accounts &#x26; Blobs</summary>

**Open Storage**

[Azure Storage Account](https://red.infiltr8.io/cloud-cicd-pentesting/azure-ad/movement/aazure-resources/storage-accounts) are Microsoft's cloud storage solution, similar to Amazon S3. It includes several services like the [Blob storage](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction), for unstructured data (images, videos, and documents..).

<img src="https://329872044-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMdUKdzuqIuObdvCB3mUR%2Fuploads%2Fgit-blob-86ba8be071483c57c2aadb673bcbbb6c183706ec%2Fimage.png?alt=media" alt="" data-size="original">

**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](https://github.com/NetSPI/MicroBurst) (Powershell) can then be used to **brute-force** storage account names, containers, and files (blobs):

```powershell
# 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):

`https://<storage_account_name>.blob.core.windows.net/newcontainer?sp=r&st=2021-09-26T18:15:21Z&se=2021-10-27T02:14:21Z&spr=https&sv=2021-07-08&sr=c&sig=7S%2BZySOgy4aA3Dk0V1cJyTSIf1cW%2Fu3WFkhHV32%2B4PE%3D`

Use [**Storage Explorer**](https://azure.microsoft.com/en-us/features/storage-explorer/) to access the data

</details>

<details>

<summary>Enumerate Azure Container Registry (ACR)</summary>

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.**

{% hint style="warning" %}
Authorizing anonymous pulls can be done as follows (need permissions)

```
az acr update --name <registry-name> --anonymous-pull-enabled true
```

{% endhint %}

If we know such registry name and images, we can pull it as follows

```bash
docker pull myregistry.azurecr.io/myimage:latest
```

</details>

### User Enumeration

The goal is to[ **compile a list of possible valid email addresses for the targeted company**](https://red.infiltr8.io/redteam/credentials/passwd/generate-wordlists)**,** aiming to identify valid accounts using tools and techniques below.

{% tabs %}
{% tab title="Manually" %}
The GetCredentialType API can be used for username enumeration.

{% hint style="danger" %}
Ensure that the domain is managed ([refer to this section](#check-if-company-is-using-azure-a-d)) to guarantee accurate results when using this technique. If it doesn't, unmanaged domains can return 0, leading to false positives
{% endhint %}

```bash
# 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'
```

{% endtab %}

{% tab title="o365spray" %}
[o365spray](https://github.com/0xZDH/o365spray?tab=readme-ov-file#spraying) (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

{% hint style="info" %}
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'.
{% endhint %}

```bash
# --enum-module: enum module (autologon, oauth2, office, onedrive, rst)
# --domain: target domain
# --enum: user enum mode
python o365spray --enum -U usernames.txt --domain <TARGET.COM> --enum-module rst
```

{% endtab %}

{% tab title="o365creeper" %}
[o365creeper](https://github.com/LMGsec/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.

```bash
# 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
```

{% endtab %}

{% tab title="onedrive\_user\_enum" %}
[onedrive\_user\_enum](https://github.com/nyxgeek/onedrive_user_enum) (Python) can be used to validate O365 users trough the OneDrive API.

```bash
# -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
```

{% endtab %}

{% tab title="AADInternals" %}
We can check if a user exists in a tenant using [AADInternals](https://github.com/Gerenios/AADInternals) (Powershell).

```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
```

{% endtab %}
{% endtabs %}

## Resources

{% embed url="<https://github.com/0xJs/CARTP-cheatsheet/blob/main/recon.md>" %}

{% embed url="<https://cloud.hacktricks.wiki/en/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/index.html>" %}
