GKE Rapid Secret GET Activity Against Multiple Objects


Description

Detects an unusual volume of GKE API get requests against multiple distinct Secret objects from the same client fingerprint (user, source IP, and user agent) within the rule lookback window. This can indicate credential access or in-cluster reconnaissance, where a user or token is used to enumerate and retrieve sensitive data such as service account tokens, registry credentials, TLS material, or application configuration. Failed get requests are included and can signal RBAC probing; system service accounts are excluded only when secret reads succeed, since failed secret access by a service account may indicate compromise or misconfiguration worth investigating.

Query · esql

from logs-gcp.audit-* metadata _id, _index, _version
| where data_stream.dataset == "gcp.audit"
    and service.name == "k8s.io"
    and event.action == "io.k8s.core.v1.secrets.get"
    and source.ip is not null
    and client.user.email is not null
    and not to_string(source.ip) in ("127.0.0.1", "::1")
    and not (
      (client.user.email in ("system:kube-controller-manager", "system:kube-scheduler") or client.user.email like "system:serviceaccount:*")
      and event.outcome == "success"
    )
    and not gcp.audit.resource_name like "*sh.helm.release.*"
| stats
    Esql.gcp_audit_resource_name_count_distinct = count_distinct(gcp.audit.resource_name),
    Esql.gcp_audit_resource_name_values = values(gcp.audit.resource_name),
    Esql.event_outcome_values = values(event.outcome),
    Esql.timestamp_values = values(@timestamp)
  by client.user.email, source.ip, user_agent.original
| where Esql.gcp_audit_resource_name_count_distinct >= 3
| keep client.user.email, source.ip, user_agent.original, Esql.gcp_audit_resource_name_count_distinct, Esql.gcp_audit_resource_name_values, Esql.event_outcome_values, Esql.timestamp_values

Known false positives

  • Startup, Helm, or controllers may legitimately touch many secrets in one window; tune by client.user.email, namespace, or IP allowlists when baselined.

Analyst notes

Investigating GKE Rapid Secret GET Activity Against Multiple Objects

This rule surfaces clusters of get operations on secrets where the same identity and client path (client.user.email, source.ip, user_agent.original) touch several different secret resource paths within the lookback window. Allowed and denied outcomes are included: successful reads may indicate harvesting; repeated failure responses can still signal reconnaissance or RBAC probing. System service accounts and core controllers are excluded only for successful secret reads, failed attempts from those identities still alert.

Investigation steps

  • Inspect Esql.event_outcome_values for a mix of success vs failure and whether failures cluster on sensitive namespaces.
  • Map the identity to RBAC and namespace scope; review Esql.gcp_audit_resource_name_values for high-value targets (tokens, registry credentials, TLS bundles, application secrets).
  • Pivot on the same source.ip and user for follow-on API activity (exec, pod create, role changes, broad list on secrets).
  • Validate against expected automation (CI, GitOps, backup, in-cluster controllers) before treating as malicious.

False positives

  • Controllers and Helm may legitimately read many secrets in one window; tune exclusions after baselining known automation.

Setup

The GCP Fleet integration with GKE audit logs enabled is required to be compatible with this rule.

Raw source GKE Rapid Secret GET Activity Against Multiple Objects · Elastic TOML
Esc
Published by elastic/detection-rules ↗, licensed under Elastic License 2.0 ↗. Reproduced here unmodified.
[metadata]
creation_date = "2026/07/07"
integration = ["gcp"]
maturity = "production"
updated_date = "2026/07/07"

[rule]
author = ["Elastic"]
description = """
Detects an unusual volume of GKE API get requests against multiple distinct Secret objects from the same client
fingerprint (user, source IP, and user agent) within the rule lookback window. This can indicate credential access or
in-cluster reconnaissance, where a user or token is used to enumerate and retrieve sensitive data such as service
account tokens, registry credentials, TLS material, or application configuration. Failed get requests are included and
can signal RBAC probing; system service accounts are excluded only when secret reads succeed, since failed secret access
by a service account may indicate compromise or misconfiguration worth investigating.
"""
false_positives = [
    """
    Startup, Helm, or controllers may legitimately touch many secrets in one window; tune by client.user.email,
    namespace, or IP allowlists when baselined.
    """,
]
from = "now-6m"
language = "esql"
license = "Elastic License v2"
name = "GKE Rapid Secret GET Activity Against Multiple Objects"
note = """## Triage and analysis

### Investigating GKE Rapid Secret GET Activity Against Multiple Objects

This rule surfaces clusters of `get` operations on secrets where the same identity and client path
(`client.user.email`, `source.ip`, `user_agent.original`) touch several different secret resource paths within the
lookback window. Allowed and denied outcomes are included: successful reads may indicate harvesting; repeated
failure responses can still signal reconnaissance or RBAC probing. System service accounts and core controllers are
excluded only for successful secret reads, failed attempts from those identities still alert.

### Investigation steps

- Inspect `Esql.event_outcome_values` for a mix of success vs failure and whether failures cluster on sensitive namespaces.
- Map the identity to RBAC and namespace scope; review `Esql.gcp_audit_resource_name_values` for high-value targets (tokens, registry
  credentials, TLS bundles, application secrets).
- Pivot on the same `source.ip` and user for follow-on API activity (exec, pod create, role changes, broad `list` on secrets).
- Validate against expected automation (CI, GitOps, backup, in-cluster controllers) before treating as malicious.

### False positives

- Controllers and Helm may legitimately read many secrets in one window; tune exclusions after baselining known automation.

## Setup

The GCP Fleet integration with GKE audit logs enabled is required to be compatible with this rule."""
references = [
    "https://attack.mitre.org/techniques/T1552/007/",
]
risk_score = 73
rule_id = "4780a3d6-e6a7-490c-9afb-9c5fbb220b9a"
severity = "high"
tags = [
    "Domain: Cloud",
    "Domain: Kubernetes",
    "Data Source: GCP",
    "Data Source: Google Cloud Platform",
    "Use Case: Threat Detection",
    "Tactic: Credential Access",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-gcp.audit-* metadata _id, _index, _version
| where data_stream.dataset == "gcp.audit"
    and service.name == "k8s.io"
    and event.action == "io.k8s.core.v1.secrets.get"
    and source.ip is not null
    and client.user.email is not null
    and not to_string(source.ip) in ("127.0.0.1", "::1")
    and not (
      (client.user.email in ("system:kube-controller-manager", "system:kube-scheduler") or client.user.email like "system:serviceaccount:*")
      and event.outcome == "success"
    )
    and not gcp.audit.resource_name like "*sh.helm.release.*"
| stats
    Esql.gcp_audit_resource_name_count_distinct = count_distinct(gcp.audit.resource_name),
    Esql.gcp_audit_resource_name_values = values(gcp.audit.resource_name),
    Esql.event_outcome_values = values(event.outcome),
    Esql.timestamp_values = values(@timestamp)
  by client.user.email, source.ip, user_agent.original
| where Esql.gcp_audit_resource_name_count_distinct >= 3
| keep client.user.email, source.ip, user_agent.original, Esql.gcp_audit_resource_name_count_distinct, Esql.gcp_audit_resource_name_values, Esql.event_outcome_values, Esql.timestamp_values
'''

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

[[rule.threat.technique]]
id = "T1552"
name = "Unsecured Credentials"
reference = "https://attack.mitre.org/techniques/T1552/"

[[rule.threat.technique.subtechnique]]
id = "T1552.007"
name = "Container API"
reference = "https://attack.mitre.org/techniques/T1552/007/"

[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"

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.