Azure Kubernetes RoleBinding or ClusterRoleBinding Created


Description

Detects when a RoleBinding or ClusterRoleBinding is created in Azure Kubernetes Service (AKS) or Arc-enabled Kubernetes clusters. Role bindings grant permissions to Kubernetes subjects (users, groups, or service accounts) by binding them to roles with specific permissions. Adversaries with appropriate access may create malicious role bindings to escalate privileges, assign cluster-admin roles, or maintain persistent access to the Kubernetes cluster. This detection applies to both AKS managed clusters and Arc-enabled connected clusters.

Query · python

from panther_azureactivity_helpers import (
    azure_activity_alert_context,
    azure_activity_success,
    extract_resource_name_from_id,
)

ROLEBINDING_OPERATIONS = [
    # Arc-enabled Kubernetes clusters
    "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/ROLEBINDINGS/WRITE",
    "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/CLUSTERROLEBINDINGS/WRITE",
    # AKS managed clusters
    "MICROSOFT.CONTAINERSERVICE/MANAGEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/ROLEBINDINGS/WRITE",
    (
        "MICROSOFT.CONTAINERSERVICE/MANAGEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/"
        "CLUSTERROLEBINDINGS/WRITE"
    ),
]


def rule(event):
    return event.get(
        "operationName", ""
    ).upper() in ROLEBINDING_OPERATIONS and azure_activity_success(event)


def title(event):
    operation = event.get("operationName", "").upper()
    binding_type = "ClusterRoleBinding" if "CLUSTERROLEBINDINGS" in operation else "RoleBinding"

    resource_id = event.get("resourceId", "<UNKNOWN_RESOURCE>")
    cluster_name = extract_resource_name_from_id(resource_id, "connectedClusters", default="")
    if not cluster_name:
        cluster_name = extract_resource_name_from_id(
            resource_id, "managedClusters", default="<UNKNOWN_CLUSTER>"
        )

    title_str = f"Azure Kubernetes {binding_type} Created in [{cluster_name}]"
    return title_str


def alert_context(event):
    context = azure_activity_alert_context(event)

    operation = event.get("operationName", "").upper()
    context["binding_type"] = (
        "cluster_role_binding" if "CLUSTERROLEBINDINGS" in operation else "role_binding"
    )

    resource_id = event.get("resourceId", "")

    cluster_name = extract_resource_name_from_id(resource_id, "connectedClusters", default="")
    if cluster_name:
        context["cluster_name"] = cluster_name
        context["cluster_type"] = "arc_enabled"
    else:
        cluster_name = extract_resource_name_from_id(resource_id, "managedClusters", default="")
        if cluster_name:
            context["cluster_name"] = cluster_name
            context["cluster_type"] = "aks_managed"

    return context

Analyst notes

  1. Query Azure Monitor Activity logs for all Kubernetes RBAC operations (rolebinding creation, clusterrolebinding creation, role modifications) by the callerIpAddress in the 24 hours before and after the alert
  2. Find all rolebinding and clusterrolebinding creations across all Kubernetes clusters in the past 6 hours to identify if this is part of a privilege escalation campaign
  3. Check if the callerIpAddress has created role bindings in the past 90 days to determine if this is typical cluster administration activity
Raw source Azure Kubernetes RoleBinding or ClusterRoleBinding Created · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
Filename: azure_kubernetes_rolebinding_created.py
RuleID: "Azure.MonitorActivity.Kubernetes.RoleBindingCreated"
DisplayName: "Azure Kubernetes RoleBinding or ClusterRoleBinding Created"
Enabled: true
LogTypes:
  - Azure.MonitorActivity
Severity: Medium
Description: >
  Detects when a RoleBinding or ClusterRoleBinding is created in Azure Kubernetes Service (AKS)
  or Arc-enabled Kubernetes clusters. Role bindings grant permissions to Kubernetes subjects
  (users, groups, or service accounts) by binding them to roles with specific permissions.
  Adversaries with appropriate access may create malicious role bindings to escalate privileges,
  assign cluster-admin roles, or maintain persistent access to the Kubernetes cluster. This
  detection applies to both AKS managed clusters and Arc-enabled connected clusters.
Reports:
  MITRE ATT&CK:
    - TA0004:T1078.004 # Privilege Escalation: Valid Accounts - Cloud Accounts
    - TA0003:T1098 # Persistence: Account Manipulation
Tags:
  - Privilege Escalation
  - Persistence
  - Valid Accounts
  - Cloud Accounts
  - Account Manipulation
Runbook: |
  1. Query Azure Monitor Activity logs for all Kubernetes RBAC operations (rolebinding creation, clusterrolebinding creation, role modifications) by the callerIpAddress in the 24 hours before and after the alert
  2. Find all rolebinding and clusterrolebinding creations across all Kubernetes clusters in the past 6 hours to identify if this is part of a privilege escalation campaign
  3. Check if the callerIpAddress has created role bindings in the past 90 days to determine if this is typical cluster administration activity
Reference: https://github.com/elastic/detection-rules/blob/main/rules/integrations/azure/privilege_escalation_kubernetes_aks_rolebinding_created.toml
SummaryAttributes:
  - resourceId
  - callerIpAddress
  - correlationId
  - location
Tests:
  - Name: Arc-enabled Cluster RoleBinding Created
    ExpectedResult: true
    Log:
      {
        "time": "2025-12-22T10:30:00.0000000Z",
        "resourceId": "/subscriptions/12345678-1234-1234-1234-123456789abc/resourceGroups/kubernetes-rg/providers/Microsoft.Kubernetes/connectedClusters/arc-cluster-01/rbac.authorization.k8s.io/rolebindings/malicious-binding",
        "operationName": "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/ROLEBINDINGS/WRITE",
        "operationVersion": "2021-10-01",
        "category": "Administrative",
        "resultType": "Success",
        "resultSignature": "200",
        "callerIpAddress": "1.1.1.1",
        "correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "level": "Informational",
        "location": "eastus",
        "tenantId": "87654321-4321-4321-4321-111111111111"
      }
  - Name: Arc-enabled Cluster ClusterRoleBinding Created
    ExpectedResult: true
    Log:
      {
        "time": "2025-12-22T11:15:00.0000000Z",
        "resourceId": "/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/k8s-arc-rg/providers/Microsoft.Kubernetes/connectedClusters/production-arc/rbac.authorization.k8s.io/clusterrolebindings/cluster-admin-binding",
        "operationName": "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/CLUSTERROLEBINDINGS/WRITE",
        "category": "Administrative",
        "resultType": "Succeeded",
        "callerIpAddress": "2.2.2.2",
        "correlationId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
        "level": "Information",
        "location": "westeurope",
        "tenantId": "22222222-2222-2222-2222-222222222222"
      }
  - Name: AKS Managed Cluster RoleBinding Created
    ExpectedResult: true
    Log:
      {
        "time": "2025-12-22T12:00:00.0000000Z",
        "resourceId": "/subscriptions/33333333-3333-3333-3333-333333333333/resourceGroups/aks-prod/providers/Microsoft.ContainerService/managedClusters/aks-prod-01/rbac.authorization.k8s.io/rolebindings/dev-binding",
        "operationName": "MICROSOFT.CONTAINERSERVICE/MANAGEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/ROLEBINDINGS/WRITE",
        "category": "Administrative",
        "resultType": "Success",
        "callerIpAddress": "3.3.3.3",
        "correlationId": "c3d4e5f6-a7b8-9012-cdef-333333333333",
        "level": "Informational",
        "location": "centralus",
        "tenantId": "33333333-3333-3333-3333-333333333333"
      }
  - Name: AKS Managed Cluster ClusterRoleBinding Created Case Insensitive
    ExpectedResult: true
    Log:
      {
        "time": "2025-12-22T13:00:00.0000000Z",
        "resourceId": "/subscriptions/44444444-4444-4444-4444-444444444444/resourceGroups/aks-dev/providers/Microsoft.ContainerService/managedClusters/aks-dev-cluster/rbac.authorization.k8s.io/clusterrolebindings/escalation-binding",
        "operationName": "microsoft.containerservice/managedclusters/rbac.authorization.k8s.io/clusterrolebindings/write",
        "category": "Administrative",
        "resultType": "Success",
        "callerIpAddress": "4.4.4.4",
        "correlationId": "d4e5f6a7-b8c9-0123-def0-222222222222",
        "level": "Information",
        "location": "westus",
        "tenantId": "44444444-4444-4444-4444-444444444444"
      }
  - Name: Different Operation
    ExpectedResult: false
    Log:
      {
        "time": "2025-12-22T15:00:00.0000000Z",
        "resourceId": "/subscriptions/66666666-6666-6666-6666-666666666666/resourceGroups/aks-prod/providers/Microsoft.ContainerService/managedClusters/aks-prod-01/rbac.authorization.k8s.io/roles/custom-role",
        "operationName": "MICROSOFT.CONTAINERSERVICE/MANAGEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/ROLES/WRITE",
        "category": "Administrative",
        "resultType": "Success",
        "callerIpAddress": "6.6.6.6",
        "correlationId": "f6a7b8c9-d0e1-2345-f012-678901234567",
        "tenantId": "66666666-6666-6666-6666-666666666666"
      }

# ------ paired body: azure_kubernetes_rolebinding_created.py ------

from panther_azureactivity_helpers import (
    azure_activity_alert_context,
    azure_activity_success,
    extract_resource_name_from_id,
)

ROLEBINDING_OPERATIONS = [
    # Arc-enabled Kubernetes clusters
    "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/ROLEBINDINGS/WRITE",
    "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/CLUSTERROLEBINDINGS/WRITE",
    # AKS managed clusters
    "MICROSOFT.CONTAINERSERVICE/MANAGEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/ROLEBINDINGS/WRITE",
    (
        "MICROSOFT.CONTAINERSERVICE/MANAGEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/"
        "CLUSTERROLEBINDINGS/WRITE"
    ),
]


def rule(event):
    return event.get(
        "operationName", ""
    ).upper() in ROLEBINDING_OPERATIONS and azure_activity_success(event)


def title(event):
    operation = event.get("operationName", "").upper()
    binding_type = "ClusterRoleBinding" if "CLUSTERROLEBINDINGS" in operation else "RoleBinding"

    resource_id = event.get("resourceId", "<UNKNOWN_RESOURCE>")
    cluster_name = extract_resource_name_from_id(resource_id, "connectedClusters", default="")
    if not cluster_name:
        cluster_name = extract_resource_name_from_id(
            resource_id, "managedClusters", default="<UNKNOWN_CLUSTER>"
        )

    title_str = f"Azure Kubernetes {binding_type} Created in [{cluster_name}]"
    return title_str


def alert_context(event):
    context = azure_activity_alert_context(event)

    operation = event.get("operationName", "").upper()
    context["binding_type"] = (
        "cluster_role_binding" if "CLUSTERROLEBINDINGS" in operation else "role_binding"
    )

    resource_id = event.get("resourceId", "")

    cluster_name = extract_resource_name_from_id(resource_id, "connectedClusters", default="")
    if cluster_name:
        context["cluster_name"] = cluster_name
        context["cluster_type"] = "arc_enabled"
    else:
        cluster_name = extract_resource_name_from_id(resource_id, "managedClusters", default="")
        if cluster_name:
            context["cluster_name"] = cluster_name
            context["cluster_type"] = "aks_managed"

    return context

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.