[New] Kubernetes Rapid Secret GET Activity Against Multiple Objects (#5967)
* [New] Kubernetes Rapid Secret GET Activity Against Multiple Objects Detects multiple k8 get secret calls for unique secret names in a short period of time (rule interval default to every 5m): * Update credential_access_kubernetes_multiple_secret_retrieval_burst.toml * Update credential_access_kubernetes_multiple_secret_retrieval_burst.toml * Update credential_access_kubernetes_multiple_secret_retrieval_burst.toml * Update credential_access_kubernetes_multiple_secret_retrieval_burst.toml
This commit is contained in:
+94
@@ -0,0 +1,94 @@
|
||||
[metadata]
|
||||
creation_date = "2026/04/22"
|
||||
integration = ["kubernetes"]
|
||||
maturity = "production"
|
||||
updated_date = "2026/04/22"
|
||||
|
||||
[rule]
|
||||
author = ["Elastic"]
|
||||
description = """
|
||||
This rule detects an unusual volume of Kubernetes API get requests against multiple distinct Secret objects from the same client
|
||||
fingerprint (user, source IP, and user agent) within a defined 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 also included, as they may reveal RBAC boundaries,
|
||||
confirm the existence of targeted secrets, or reflect automated probing activity.
|
||||
"""
|
||||
from = "now-6m"
|
||||
language = "esql"
|
||||
license = "Elastic License v2"
|
||||
name = "Kubernetes Rapid Secret GET Activity Against Multiple Objects"
|
||||
note = """## Triage and analysis
|
||||
|
||||
### Investigating Kubernetes Rapid Secret GET Activity Against Multiple Objects
|
||||
|
||||
This rule surfaces clusters of `get` operations on the `secrets` API where the same identity and client path
|
||||
(`user.name`, `source.ip`, `user_agent.original`) touch several different secret names within the rule lookback window.
|
||||
**Allowed and denied** outcomes are included: successful reads may indicate harvesting; repeated **forbidden** or
|
||||
**unauthorized** responses can still signal reconnaissance, RBAC probing, or scripted spray against secret names that
|
||||
exist in the cluster.
|
||||
|
||||
### Investigation steps
|
||||
|
||||
- Inspect `Esql.outcome` for a mix of allow vs deny and whether failures cluster on sensitive namespaces.
|
||||
- Map the identity to RBAC and namespace scope; review `Esql.secrets_names` and `Esql.namespaces` 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
|
||||
|
||||
- Startup, Helm, or controllers may legitimately touch many secrets in one window; tune by user, namespace, or IP
|
||||
allowlists when baselined.
|
||||
"""
|
||||
references = [
|
||||
"https://attack.mitre.org/techniques/T1552/007/",
|
||||
]
|
||||
risk_score = 73
|
||||
rule_id = "b4c8e2a1-9f3d-4e7c-a2b1-0d5e6f7a8b9c"
|
||||
severity = "high"
|
||||
tags = [
|
||||
"Data Source: Kubernetes",
|
||||
"Domain: Kubernetes",
|
||||
"Use Case: Threat Detection",
|
||||
"Tactic: Credential Access",
|
||||
"Resources: Investigation Guide",
|
||||
]
|
||||
timestamp_override = "event.ingested"
|
||||
type = "esql"
|
||||
query = '''
|
||||
from logs-kubernetes.audit_logs-* metadata _id, _index, _version
|
||||
| where event.dataset == "kubernetes.audit_logs"
|
||||
and event.action == "get"
|
||||
and kubernetes.audit.objectRef.resource == "secrets"
|
||||
and source.ip is not null and user.name is not null
|
||||
and not to_string(source.ip) in ("127.0.0.1", "::1") and
|
||||
not user.name in ("system:kube-controller-manager", "system:kube-scheduler") and
|
||||
not kubernetes.audit.objectRef.name like "sh.helm.release.*"
|
||||
| stats
|
||||
Esql.unique_credentials = count_distinct(kubernetes.audit.objectRef.name),
|
||||
Esql.secrets_names = values(kubernetes.audit.objectRef.name),
|
||||
Esql.namespaces = values(kubernetes.audit.objectRef.namespace),
|
||||
Esql.outcome = values(`kubernetes.audit.annotations.authorization_k8s_io/decision`)
|
||||
by user.name, source.ip, user_agent.original
|
||||
| where Esql.unique_credentials >= 3
|
||||
| KEEP user.name, source.ip, user_agent.original, Esql.*
|
||||
'''
|
||||
|
||||
[[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/"
|
||||
|
||||
Reference in New Issue
Block a user