Project Miaow (Privilege Escalation from an ARM template)
Managed Identity Adds Owner
This article describes how a user with limited permissions on a resource group can elevate its privileges to a Subscription Owner! O.M.G
I while back I was doing some research on the possibility how to run a PowerShell script from an Azure Policy, and see if this method could be used to create persistence in Microsoft Azure.
Looking at the possibilities the most common method would be using an ARM template and use this to run some code. But to create and assign an Azure Policy to run a PowerShell script at a certain time already requires a privileged account, so that was not an option.
Mission failed
While going through my notes and drawings on my Desktop buddy (thanks Microsoft Security, I still love it) I suddenly got struck by another idea.
Could a user escalate its privileges using a deployment template?
Hope suddenly came back and I cleared out my drawing board and started to workout a new scenario.
To get this working I needed some prerequisites in place
- User account with deployment permissions
- ARM template
- User-Assigned Managed Identity
Although I have worked with deployment scripts before in ARM templates, I see it as a good habit to check the documentation and see if anything has changed. Microsoft did an excellent job on creating a Microsoft Learn page, included some nice examples and exercises.
How does the DeploymentScript resource work?
Good question!
As we could see on the Microsoft Learn page, A deploymentScript uses a couple of resources. The most important part to know is that a Azure Container Instance (ACI) is deployed together with a Storage Account.
We also need to have user-assigned managed identity to run the deployment script in the correct context.
Once these resources are created the DeploymentScript itself is sent to the storage account and executed in the ACI.
John Savill did a video on this that can be found YouTube
Building the PoC
In general, any user that deploys an ARM or Bicep template has at least contributor permissions to a resource group or subscription in Azure. So I decided to start from that and then decrease the permissions to the minimum set required to execute the attack. I will code back to this later in this article.
I fired up my VSCode and started hitting my keyboard like a maniac and produced some ARM templates and a PowerShell script in about an hour and Project Miaow was born.
As always, most time goes into creating and aligning the ASCII art that every good script needs.
Preparing the scenario
In the image below the famous Mr. Harland Sanders is logged in to PowerShell. For the people who don’t know him, or don’t recognize the photo, He is The Mr. Kentucky Fried Chicken. Not to mistake with Pollos Hermanos for all breaking bad fans.
Mr. Harland has the limited role deployment administrator
on resource group
level, and only has assign
permissions on a user-assigned managed identity called super-owner
. (This is less permissions than a contributor
would have!
"permissions": [
{
"actions": [
"Microsoft.ManagedIdentity/userAssignedIdentities/*/read",
"Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action"
],
"notActions": [],
"dataActions": [],
"notDataActions": []
}
]
The user-assigned managed Identity has owner
permissions on subscription level. This might sound strange at first, but is actually a common scenario when using automation to clean-up orphaned security principals from the Azure Role assignments.
When checking the permissions of Harland in PowerShell we can see that only the Deployment Administrator
is assigned.
Proof of Concept
Mr. Harland is logs in to PowerShell and queries all resources he has access to. As we can see he can only see the managed identity with the name super-owner.
To execute the the malicious action Harland deploys the ARM template containing the exploit to elevate his privileges by abusing the permissions of the user-assigned managed identity.
See the table above for the parameters provided in the deployment.
During the deployment a storage account, container instance and deploymentScript resource is created in the resource group kentucky-fried-veggies
The script in the deploymentScript object will be executed in the context of the use assigned managed identity.
Once the script is finished it will show the Miaow logo is displayed in the deployment script overview in the Microsoft Azure portal.
The next step is to validate the permissions that Mr. Harland had deployment administrator
are indeed elevated to a higher role. This can easily done by using the Get-AzRoleAssigment
cmdLet followed by the principalId
that was provided during the deployment 301dfac7–8f45–48ac-9868-e1f0e875385c
And BAM we are an O W N E R of the subscription now.
Lessons learned
The privileges that can be assigned depends on the permission scope of the user-assigned managed identity that is attached to the deployment script during the deployment.
Although the scenario looks like to work as it was designed by Microsoft, I still think they are taking a risk by providing a way to escalate privileges by abusing a managed identity that has more permissions than the user executing the deployment.
In the script miaow.ps1
used in the deployment, we are using the bearerToken of the user-assigned managed identity to authenticate against the REST API. This is done to avoid any dependencies on PowerShell modules to assign the permissions. Because we are able to read the bearer token of the MI, We can return this value as an output of the ARM template deployment and craft thus create an ARM template for credential theft
.
This also means that the access token can be (ab)used outside of the Azure environment by a malicious user.
As I did in my ARM template, it is possible to reference to a script that is public accessibly. In my case I referenced to the miaow.ps1
file on my GitHub, but this same method can be used to execute advanced pen testing tools without being detected.
Clearing logs, removing other admin accounts, hijacking the subscription and many other attacks can be executed using this method.
Final Note
The issue was reported to Microsoft MSRC under VULN-104756
on July 14th and acknowledged two months later. They will update the documentation to call out the risk more explicitly.
This still does not fix the issue that malicious code can be executed from a deployment script that can cause severe damage.
There is no real protection against this risk other than a good governance plan for identities in Microsoft Azure.
Project link
Happy Hacking!