TLDR;
It is often assumed that the Contributor role cannot read secrets from key vaults. This is inaccurate and is often abused when doing Azure penetration testing. We’ll understand why and how we can possibly address this.
- Contributor roles gets often assigned to service principals and users in dev and testing teams
- By default, Contributors can grant self-permission to read secrets. This is undesirable
- We follow Microsoft’s recommendation and secure against this behavior using RBAC controlled secrets
Screenshots from the owner account are in Dark Mode
Screenshots from our penetration tester are in Light Mode
Contributor’s Keys to the Kingdom
Following up on the previous article Azure AD Roles Vs. Azure Resources Roles let us expand a bit on some useful RBAC configurations. Here’s a scenario that is all too common when going through an Azure penetration testing exercise.
A subscription is created for the development team. In the subscription is a key vault with keys, secrets and/or certificates that are usually used by apps. The key vault isn’t and shouldn’t normally be accessed by the dev team directly.
As the same time, most of the devs are assigned a Contributor role to make it easy for them to manage their resources. This has an inherent risk associated.
At a certain stage of the Azure penetration testing, the consultant gets their hands on a dev account. This allows them to manipulate the key vault to access the secrets. This is undesirable as these vaults could contain sensitive secrets like a break glass admin passwords for example.
Unfortunately, this is known and expected as mentioned by Microsoft here.

Revealing Secrets
How does the above message translate in an Azure penetration testing engagement? Here is a typical scenario. We have our user, a Contributor, scoped to the subscription.

If our penetration tester tries to access a secret, by default, they are denied access.

However, if the account is compromised, the penetration tester (or malicious account owner) can work around this by creating an access policy with self-granting permissions.

Once grated, they can access the secret and reveal its value.

Why Custom Roles Fail
We can try preventing this by using custom roles. For example, here we created a custom role which is a clone of the Contributor role but with two caveats.
First, the role is scoped to the key vault.
Second, we deny changes to the access policy by excluding the following permission: Microsoft.KeyVault/vaults/accessPolicies/write

In figure 7 is the built in, non modified, Contributor role, which has permission to change access policies. Below it, in figure 8, is the custom contributor role.


However, when we apply this permission to our user, it doesn’t seem to make an effect. Here is why…
Access Policies Vs. RBAC
You might have noticed in the previous screenshots the “Permissions model” when we visit the access policies. The previous key vault was protected with a “Vault access policy”. This is the reason our RBAC didn’t apply. And that allowed the contributor user (or our penetration tester) to create a policy allowing themselves to reveal the secret.

Alternatively, we could have used Azure RBAC. Unlike access policies that apply to key vaults only, RBAC can also apply to individual keys, secret, and certificate.
Microsoft Recommends
Microsoft recommends using RBAC over Access Policies here.
Following Microsoft’s recommendations, we create another vault, however this time, we will select the permission model to be RBAC instead of access policy.

As we already learned, the owner is now able to control access to each secret individually using RBAC.
In figure 10, we can see a secret protected by access policy and it doesn’t have any IAM control options. In figure 11, a secret protected with IAM.


Revealing Secrets?
Now what happens a contributor role tries to access the secret?
They are denied; with a message stating that RBAC roles don’t allow this action.

If the Azure penetration tester tries to work around this by changing the “Access policy model” they will also be denied.

With that we would have successfully achieved our objective of denying Contributor users from directly revealing secrets.
Summary
Contributor roles is often assigned to users. However, it indirectly allows for revealing secrets which can be abused during an Azure penetration testing exercise. We tested the following scenarios:
- Protect Key vault with access policies.
- Protection failed. Both Contributor and Custom-Contributor can change “Permission model” on access policies and read secrets
- Protect secrets with RBAC
- Protection succeeded. Neither Contributor nor Customer-Contributor can change “Permission model” on access policies and read secrets
References
https://docs.microsoft.com/en-us/azure/key-vault/general/rbac-migration
https://docs.microsoft.com/en-us/azure/role-based-access-control/custom-roles-portal
https://docs.microsoft.com/en-us/azure/key-vault/general/security-features