Detection rules › Elastic

GKE Suspicious Assignment of Controller Service Account

Status
production
Severity
medium
Time window
6m
Author
Elastic
Source
github.com/elastic/detection-rules

Detects a request to attach a built-in kube-controller-manager service account to a pod running in the kube-system namespace on GKE. These service accounts are admin-equivalent and are not normally assigned to arbitrary pods. An attacker who can create pods in kube-system can abuse these tokens for cluster-wide privilege escalation.

Known false positives

  • Built-in controller service accounts are rarely assigned to running pods. False positives should be rare; allowlist documented platform automation by actor when baselined.

MITRE ATT&CK coverage

TacticTechniques
Execution
Privilege Escalation

Telemetry coverage

PlatformRecord / event type
Kubernetescreate-pods: create pods

Rules detecting the same action

These rules filter on the same operation.

Rule body

[metadata]
creation_date = "2026/07/10"
integration = ["gcp"]
maturity = "production"
updated_date = "2026/07/10"

[rule]
author = ["Elastic"]
description = """
Detects a request to attach a built-in kube-controller-manager service account to a pod running in the kube-system
namespace on GKE. These service accounts are admin-equivalent and are not normally assigned to arbitrary pods. An attacker
who can create pods in kube-system can abuse these tokens for cluster-wide privilege escalation.
"""
false_positives = [
    """
    Built-in controller service accounts are rarely assigned to running pods. False positives should be rare; allowlist
    documented platform automation by actor when baselined.
    """,
]
from = "now-6m"
index = ["logs-gcp.audit-*"]
language = "kuery"
license = "Elastic License v2"
name = "GKE Suspicious Assignment of Controller Service Account"
note = """## Triage and analysis

### Investigating GKE Suspicious Assignment of Controller Service Account

This rule flags pod create events in kube-system that assign a built-in kube-controller-manager service account.

### Possible investigation steps

- Review `client.user.email`, `gcp.audit.request.spec.serviceAccountName`, and container images.
- Determine whether the pod aligns with expected platform operations.
- Assess permissions of the assigned service account and hunt for follow-on secret or RBAC activity.

### False positive analysis

- Built-in controller service accounts should not be mounted on user-created pods. Allowlist known automation by actor if a documented exception exists.

### Response and remediation

- Delete suspicious pods, revoke the service account token, and restrict pod create permissions in kube-system.

"""
setup = "The GCP Fleet integration with GKE audit logs enabled is required to be compatible with this rule."
references = [
    "https://www.paloaltonetworks.com/apps/pan/public/downloadResource?pagePath=/content/pan/en_US/resources/whitepapers/kubernetes-privilege-escalation-excessive-permissions-in-popular-platforms",
    "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#controller-roles",
]
risk_score = 47
rule_id = "e2f60d42-e0ea-4a03-a151-942bb5b86c0b"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Domain: Kubernetes",
    "Data Source: GCP",
    "Data Source: Google Cloud Platform",
    "Use Case: Threat Detection",
    "Tactic: Execution",
    "Tactic: Privilege Escalation",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset:gcp.audit and service.name:"k8s.io" and event.outcome:success and
event.action:"io.k8s.core.v1.pods.create" and gcp.audit.request.metadata.namespace:"kube-system" and
gcp.audit.request.spec.serviceAccountName:(
  attachdetach-controller or certificate-controller or cloud-provider or
  clusterrole-aggregation-controller or cronjob-controller or daemon-set-controller or deployment-controller or
  disruption-controller or endpoint-controller or expand-controller or generic-garbage-collector or
  horizontal-pod-autoscaler or job-controller or namespace-controller or node-controller or
  persistent-volume-binder or pod-garbage-collector or pv-protection-controller or pvc-protection-controller or
  replicaset-controller or replication-controller or resourcequota-controller or root-ca-cert-publisher or
  route-controller or service-account-controller or service-controller or statefulset-controller or ttl-controller
)
'''

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1078"
name = "Valid Accounts"
reference = "https://attack.mitre.org/techniques/T1078/"

[[rule.threat.technique.subtechnique]]
id = "T1078.001"
name = "Default Accounts"
reference = "https://attack.mitre.org/techniques/T1078/001/"

[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1610"
name = "Deploy Container"
reference = "https://attack.mitre.org/techniques/T1610/"

[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "client.user.email",
    "source.ip",
    "user_agent.original",
    "event.action",
    "event.outcome",
    "gcp.audit.resource_name",
    "gcp.audit.request.spec.serviceAccountName",
    "gcp.audit.request.spec.containers.image",
    "data_stream.namespace",
]

Stages and Predicates

Stage 1: query

data_stream.dataset:gcp.audit and service.name:"k8s.io" and event.outcome:success and
event.action:"io.k8s.core.v1.pods.create" and gcp.audit.request.metadata.namespace:"kube-system" and
gcp.audit.request.spec.serviceAccountName:(
  attachdetach-controller or certificate-controller or cloud-provider or
  clusterrole-aggregation-controller or cronjob-controller or daemon-set-controller or deployment-controller or
  disruption-controller or endpoint-controller or expand-controller or generic-garbage-collector or
  horizontal-pod-autoscaler or job-controller or namespace-controller or node-controller or
  persistent-volume-binder or pod-garbage-collector or pv-protection-controller or pvc-protection-controller or
  replicaset-controller or replication-controller or resourcequota-controller or root-ca-cert-publisher or
  route-controller or service-account-controller or service-controller or statefulset-controller or ttl-controller
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
data_stream.dataseteq
  • gcp.audit
field:"data_stream.dataset" kind:eq value:"gcp.audit"
event.actioneq
  • io.k8s.core.v1.pods.create
field:"EventType" kind:eq value:"io.k8s.core.v1.pods.create"
event.outcomeeq
  • success
field:"event.outcome" kind:eq value:"success"
gcp.audit.request.metadata.namespaceeq
  • kube-system
field:"gcp.audit.request.metadata.namespace" kind:eq value:"kube-system"
gcp.audit.request.spec.serviceAccountNamein
  • attachdetach-controller
  • certificate-controller
  • cloud-provider
  • clusterrole-aggregation-controller
  • cronjob-controller
  • daemon-set-controller
  • deployment-controller
  • disruption-controller
  • endpoint-controller
  • expand-controller
  • generic-garbage-collector
  • horizontal-pod-autoscaler
  • job-controller
  • namespace-controller
  • node-controller
  • persistent-volume-binder
  • pod-garbage-collector
  • pv-protection-controller
  • pvc-protection-controller
  • replicaset-controller
  • replication-controller
  • resourcequota-controller
  • root-ca-cert-publisher
  • route-controller
  • service-account-controller
  • service-controller
  • statefulset-controller
  • ttl-controller
field:"gcp.audit.request.spec.serviceAccountName" kind:in
service.nameeq
  • k8s.io
field:"ServiceName" kind:eq value:"k8s.io"