Getting your Trinity Audio player ready...
|
Welcome back to our in-depth look at ArgoCD and hybrid Azure attacks. In the first part of this blog, we explored how a compromised cloud identity can be used to gain unauthorized access to an AKS cluster and escalate privileges using ArgoCD. We demonstrated the risks associated with excessive permissions and the potential for container escape scenarios.
Now, in this second part, we’ll be focusing on Azure Kubernetes Workload Identity and how this feature can be exploited by attackers to move laterally and/or escalate privileges within Azure environments. Workload Identity allows Kubernetes service accounts to assume Azure principals and their associated permissions, enabling seamless access to Azure resources from within the cluster.
We’ll discuss the configuration steps required to enable Workload Identity and the various mapping options available. Through practical attack scenarios, we’ll demonstrate how attackers can abuse this feature to compromise multiple Azure principals across different tenants, perform lateral movement, and gain access to sensitive resources such as Azure Key Vault secrets.
Understanding the security implications of Azure Kubernetes Workload Identity is crucial for organizations looking to secure their hybrid Azure and Kubernetes deployments.
Let’s dive in and explore the risks and mitigation strategies associated with this powerful feature.
Azure Kubernetes Workload Identity
Kubernetes workloads deployed on Azure Kubernetes Services (AKS) clusters sometimes require having Microsoft Entra Identities with adequate permissions to access Microsoft Entra-protected resources, such as Azure Key Vault (Azure Resource Manager), etc.
There are multiple authentication and authorization options available on AKS clusters that enable “hybrid” identity permissions across environments, meaning that it essentially allows Kubernetes Service Accounts to assume Azure Principals and their derivative permissions. The newest and most recommended feature in this genre that supports AKS is Microsoft Entra Workload ID for AKS, which is supported in AKS clusters since version 1.22. It utilizes the cluster’s defined Open ID Connect (OIDC) server that will authorize and authenticate Kubernetes Service Accounts to Microsoft Entra ID resources, rather than having a static authentication credential that is saved as a Kubernetes Secret. In this scenario, we’ll demonstrate access to Azure Key Vault secrets resources.
The following steps are required to enable the Workload Identity feature for an AKS cluster:
- Enable Entra Workload ID for the AKS cluster, either by updating its “securityProfile”, or by recreating it, e.g. updating an existing AKS cluster:
- Enable Entra Workload ID for an existing cluster:
az aks update -g <RESOURCE GROUP> -n <CLUSTER> –enable-oidc-issue –enable-workload-identity - Determine OIDC server’s URL:
az aks show -g <RESOURCE GROUP> -n <CLUSTER> –query “oidcIssuerProfile.IssuerUrl” - Determine whether Entra Workload ID is enabled:
az aks show -g <RESOURCE GROUP> -n <CLUSTER> –query “securityProfile.workloadIdentity.enabled” – will be ‘true’ in case enabled
- Create or use existing User-Assigned Managed Identity or Entra ID Application, that will have the federated credentials defined:
- E.g., create a new User-Assigned Managed Identity –
az identity create -n <IDENTITY> -g <RESOURCE GROUP> -l <LOCATION> - E.g., create an Application –az ad sp create –id
- Create a Federation credential for the dedicated User-Assigned Managed Identity / Entra ID Application, that uses the cluster’s defined “oidcIssuerProfile.issuerUrl” OIDC server, and match a dedicated Kubernetes Service Account at a specific Kubernetes namespace (created at stage 4), have an Audience “api://AzureADTokenExchange”; This can be done via the CLI using the command:For Azure User-Assigned Managed Identity –
- az identity federated-credential create –name <NAME> –identity-name <MANAGED IDENTITY NAME> –resource-group <RESOURCE GROUP> –issuer <OIDC SERVER> –subject system:serviceaccount:”<NAMESPACE>”:”<SA NAME>” –audience <AUDIENCE>
- az ad app federated-credential create – name <NAME> – id <APPLICATION ID> – resource-group <RESOURCE GROUP> -issuer <OIDC SERVER> – subject system:serviceaccount:”<NAMESPACE>”:”<SA NAME>” – audience <AUDIENCE>
- Create a Kubernetes Service Account that is assigned for the Federation credential of the Azure Principal, annotate it with the following:
azure.workload.identity/client-id: <TARGET AZURE PRINCIPAL CLIENT ID>
azure.workload.identity/tenant-id: <TARGET AZURE TENANT ID> //(Optional) - Create a Kubernetes Pod that mounts the relevant Kubernetes Service Account and is labeled with the following:
azure.workload.identity/use: “true”
The following Kubernetes Service Accounts and Pods annotations can help you to configure and harden the Microsoft Entra ID feature’s overall security in your cluster:
Microsoft Entra ID Workload Identity labels and annotations
In an adequately configured AKS environment, the Kubernetes service account token will be automatically mounted to any Pod that utilizes that same service account using the Kubernetes service account’s annotations and validating authentication requests, then the credential “conversion” process is as elaborated in the diagram below:
Microsoft Entra Workload ID supports the following mappings related to a Kubernetes service account:
- “One-to-one”, where a service account references a Microsoft Entra object.
- “Many-to-one”, where multiple service accounts reference the same Microsoft Entra object.
- “One-to-many”, where a service account references multiple Microsoft Entra objects by changing the Client ID annotation.
Attack Scenarios
Cross-tenants lateral movement
In either mapping case, it’s possible to set the mapped identity to one that resides in a different Azure tenant than the cluster itself, using the elaborated above annotation – azure.workload.identity/tenant-id, set with the tenant UUID whereas the mapped Azure Principal exists.
For example:
The Azure user “ilz@researchtest.onmicrosoft.com” is currently authenticated and has permissions to our AKS cluster “xmcyber-optimized” at tenant “XM Cyber Research.” It’s bound with the “cluster-admin” Kubernetes ClusterRole and can execute commands on the Pod “default” at the “default” namespace, which has the Azure Workload Identity credentials mounted upon it.
On the remote tenant (“ModelTenant”), we created a Service Principal named “melech-external”, we added a Federated credential (“external-federated-aks”) that is set with “XM Cyber Research” tenants’ OIDC server URL that’s defined on our “xmcyber-optimized” AKS cluster, along with Kubernetes service account “default” at namespace “default”.
Using the mounted Federated credentials on our Pod, we are now authenticated to the “ModelTenant” Azure tenant as the Service Principal “melech-external”, it is set with the “Azure Kubernetes Service Cluster User Role” and “Azure Kubernetes Service RBAC Reader” Azure Resource Manager RBAC Roles that enables it to access most of the remote tenants’ AKS resources at the permitted scope, including the “aks_cluster_scenario_tester” AKS cluster.
Our Service Principal “melech-external” and the Azure RBAC Roles it’s assigned to.
Retrieving the adequate kubeconfig settings using the Az CLI, converting the authentication credential format to match this specific scenario using Azure Workload Identity, and at last – listing resources that reside at the remote cluster – “aks_cluster_scenario_tester” AKS cluster
This feature may enable an attacker to compromise multiple Azure principals with permissions over multiple Azure tenants.
“One-to-Many” for Lateral Movement
As a result of how this feature operates, as long as there are multiple Federation Credential mappings for Azure Service Principals / User-Assigned Managed Identities, and in case an attacker can either modify Kubernetes service accounts annotation to different Azure Service Principal Client IDs, or create a new Kubernetes service account with the adequate annotations – the attacker can change the mapped Azure Principal to another, to move laterally and assume other Azure principals that are having more/different permissions.
Alternatively, in case the attacker also has the required permissions to modify a Kubernetes service account are either “update” or “patch” verbs over “serviceaccounts” resources, at “core” API (default in case empty); In addition, for Microsoft Entra ID authentication with Azure RBAC in AKS, an Azure principal that has the “Microsoft.ContainerService/managedClusters/serviceaccounts/write” ‘dataAction’ assigned to it for the relevant AKS cluster/s scopes.
Also, to compromise Microsoft Entra ID principals who don’t have pre-existing federation credential mappings – the following attack vectors are possible to create new federated identity credentials:
- If the attackers also have the Azure Resource Manager’s RBAC permission–“Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write” over Azure User-Assigned Managed Identities- they can compromise them while mapping them to a Kubernetes service account it controls.
- In case the attackers also have the Microsoft Entra Directory RBAC permission – “Microsoft.directory/applications/credentials/update” over an Azure Application – they can compromise its app registrations, while mapping them to a Kubernetes service account that in their control.
An attacker with one of the permissions mentioned above can compromise the Azure principals and use their permissions.
When the abovementioned scenario is possible an attacker can use the ‘azure.workload.identity’ various annotations while setting the desired Azure service principal and matching tenant UUIDs, for example:
The following scenario continues the previous multi-tenant scenario in which the mapped Azure Principal has Azure Resource Manager permissions over AKS clusters; In this scenario, there’s another Microsoft Entra ID Application with other Azure Resource Managers’ RBAC permissions:
Entra ID Application “Caesar-dev” is assigned to the Azure Resource Manager Role “Key Vault Secrets User” that enables it to read Azure Key Vault Secrets data
“melech-external” is assigned to the Microsoft Entra ID Role “Application Administrator” over the remote Entra ID Directory, which among other things enables it to create Applications Federated Credentials for its Entra ID Applications
Using melech-external’s “Application Administrator” Application Role we could add The Entra ID Application “Caesar-dev” with new Federated credentials assigned to the “poc” Kubernetes service account at namespace “default”, At the previous AKS cluster – “xmcyber-optimized”
On the AKS cluster – “xmcyber-optimized”, we can now create a Kubernetes service account “poc” at namespace “default” that assumes the remote “Caesar-dev” app registration Federated Credential
On the AKS cluster – “xmcyber-optimized”, we had created a Kubernetes pod “poc-pod” at namespace “default” that utilizes the “poc” Kubernetes service account and assumes the remote “Caesar-dev” app registration Federated Credential, using the assumed remote App registration we could leverage “Caesar-dev” “Key Vault Secret User” built-in Azure Resource Manager Role to read secrets in the partially compromised remote tenant, in this example we look at the “dev-top-secret” Azure Key Vault and attain “top-secret” Secret.
Conclusion
To sum up, attackers who have compromised an AKS Pod in an AKS cluster that is configured to use Microsoft Entra ID for AKS may be able to leverage this feature and move laterally and/or escalate privileges to different Azure environments and principals they contain.