Detection rules › Elastic

GKE Unusual Sensitive Workload Modification

Status
production
Severity
low
Time window
6m
Group by
client.user.email, source.ip, user_agent.original
Author
Elastic
Source
github.com/elastic/detection-rules

Detects the first occurrence of create or patch activity against sensitive GKE workloads (DaemonSets, Deployments, or CronJobs) from an unusual combination of user agent, source IP, and user identity, which may indicate privilege escalation or unauthorized access within the cluster.

Known false positives

  • Emergency kubectl changes, VPN or workstation migrations, and CI runner rotation can produce new user agent, source IP, and username combinations for authorized operators. Baseline expected automation before tuning.

MITRE ATT&CK coverage

Telemetry coverage

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 the first occurrence of create or patch activity against sensitive GKE workloads (DaemonSets, Deployments, or
CronJobs) from an unusual combination of user agent, source IP, and user identity, which may indicate privilege
escalation or unauthorized access within the cluster.
"""
false_positives = [
    """
    Emergency kubectl changes, VPN or workstation migrations, and CI runner rotation can produce new user agent, source
    IP, and username combinations for authorized operators. Baseline expected automation before tuning.
    """,
]
from = "now-6m"
index = ["logs-gcp.audit-*"]
language = "kuery"
license = "Elastic License v2"
name = "GKE Unusual Sensitive Workload Modification"
note = """## Triage and analysis

### Investigating GKE Unusual Sensitive Workload Modification

This new-terms rule alerts on the first create or patch of a DaemonSet, Deployment, or CronJob from a new combination of
`user_agent.original`, `source.ip`, and `client.user.email`.

### Possible investigation steps

- Review the audit request for image, command, service account, and privileged settings changes.
- Attribute the actor to its backing identity and validate whether the source network is expected.
- Correlate with RBAC, secret, or exec activity from the same identity.

### False positive analysis

- Legitimate on-call changes from new workstations or updated kubectl versions are common in lab clusters.

### Response and remediation

- Roll back unauthorized workload changes, revoke the credential used, and tighten RBAC on workload controllers.

"""
setup = "The GCP Fleet integration with GKE audit logs enabled is required to be compatible with this rule."
references = [
    "https://heilancoos.github.io/research/2025/12/16/kubernetes.html#overly-permissive-role-based-access-control",
    "https://flare.io/learn/resources/blog/teampcp-cloud-native-ransomware",
]
risk_score = 21
rule_id = "8d97dfa3-3c51-45fb-8621-bde800c47b22"
severity = "low"
tags = [
    "Domain: Cloud",
    "Domain: Kubernetes",
    "Data Source: GCP",
    "Data Source: Google Cloud Platform",
    "Use Case: Threat Detection",
    "Tactic: Privilege Escalation",
    "Tactic: Persistence",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"

query = '''
data_stream.dataset:gcp.audit and service.name:k8s.io and event.outcome:success and user_agent.original:* and client.user.email:(* and not system\:*) and source.ip:* and event.action:(io.k8s.apps.v1.daemonsets.create or io.k8s.apps.v1.daemonsets.patch or io.k8s.apps.v1.deployments.create or io.k8s.apps.v1.deployments.patch or io.k8s.batch.v1.cronjobs.create or io.k8s.batch.v1.cronjobs.patch)
'''

[rule.new_terms]
field = "new_terms_fields"
value = ["user_agent.original", "source.ip", "client.user.email"]

[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-7d"

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

[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"

[[rule.threat.technique.subtechnique]]
id = "T1098.006"
name = "Additional Container Cluster Roles"
reference = "https://attack.mitre.org/techniques/T1098/006/"

[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 = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"

[[rule.threat.technique.subtechnique]]
id = "T1098.006"
name = "Additional Container Cluster Roles"
reference = "https://attack.mitre.org/techniques/T1098/006/"

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

[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",
    "data_stream.namespace",
]

Stages and Predicates

Stage 1: new_terms

data_stream.dataset:gcp.audit and service.name:k8s.io and event.outcome:success and user_agent.original:* and client.user.email:(* and not system\:*) and source.ip:* and event.action:(io.k8s.apps.v1.daemonsets.create or io.k8s.apps.v1.daemonsets.patch or io.k8s.apps.v1.deployments.create or io.k8s.apps.v1.deployments.patch or io.k8s.batch.v1.cronjobs.create or io.k8s.batch.v1.cronjobs.patch)

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
client.user.emailstarts_withsystem:excludes:client.user.email field:"client.user.email" value:"system:"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
client.user.emailis_not_null
  • (no value, null check)
field:"client.user.email" kind:is_not_null
data_stream.dataseteq
  • gcp.audit
field:"data_stream.dataset" kind:eq value:"gcp.audit"
event.actionin
  • io.k8s.apps.v1.daemonsets.create
  • io.k8s.apps.v1.daemonsets.patch
  • io.k8s.apps.v1.deployments.create
  • io.k8s.apps.v1.deployments.patch
  • io.k8s.batch.v1.cronjobs.create
  • io.k8s.batch.v1.cronjobs.patch
field:"EventType" kind:in
event.outcomeeq
  • success
field:"event.outcome" kind:eq value:"success"
service.nameeq
  • k8s.io
field:"ServiceName" kind:eq value:"k8s.io"
source.ipis_not_null
  • (no value, null check)
field:"src_ip" kind:is_not_null
user_agent.originalis_not_null
  • (no value, null check)
field:"aws::userAgent" kind:is_not_null