[New] Kubernetes Secret get or list with Suspicious User Agent (#5974)
* [New] Kubernetes Secret get or list via Scripting or Generic HTTP Client After obtaining Kubernetes API credentials, adversaries often reach for generic HTTP stacks and scripting runtimes (curl, wget, Python requests, Go’s default client, and similar) instead of kubectl or in-cluster controllers that advertise purpose-built user agents. Those clients are easy to drive from a stolen kubeconfig, a compromised bastion, or a reverse shell and are commonly used to enumerate or download Secret objects (tokens, registry credentials, TLS material, application keys). * ++ * Update credential_access_kubernetes_secret_access_scripting_http_clients.toml
This commit is contained in:
+99
@@ -0,0 +1,99 @@
|
||||
[metadata]
|
||||
creation_date = "2026/04/22"
|
||||
integration = ["kubernetes"]
|
||||
maturity = "production"
|
||||
updated_date = "2026/04/22"
|
||||
|
||||
[rule]
|
||||
author = ["Elastic"]
|
||||
description = """
|
||||
Detects read access to Kubernetes Secrets (`get`/`list`) with a user agent matching a curated set of non-standard or
|
||||
attacker-leaning clients, for example minimal HTTP tooling, common scripting stacks, default library fingerprints, or
|
||||
distribution-tagged strings associated with offensive-security Linux images. Legitimate in-cluster automation usually
|
||||
presents stable, purpose-specific user agents (for example controller or client-go variants used by known components).
|
||||
"""
|
||||
false_positives = [
|
||||
"""
|
||||
Operators may use ad hoc HTTP clients, scripts, or penetration-test images during approved exercises or break-glass
|
||||
maintenance; validate tickets, source IP, and identity before treating as compromise.
|
||||
""",
|
||||
"""
|
||||
Internal automation built with generic libraries can resemble suspicious user agents; baseline known jobs and tune
|
||||
by service account, namespace, or stable source IP allowlists.
|
||||
""",
|
||||
]
|
||||
index = ["logs-kubernetes.audit_logs-*"]
|
||||
language = "kuery"
|
||||
license = "Elastic License v2"
|
||||
name = "Kubernetes Secret get or list with Suspicious User Agent"
|
||||
note = """## Triage and analysis
|
||||
|
||||
### Investigating Kubernetes Secret get or list with Suspicious User Agent
|
||||
|
||||
The rule matches Kubernetes audit events for **secret** `get`/`list` where **`user_agent.original`** matches a **small
|
||||
allowlist of suspicious patterns** (scripting runtimes, bare HTTP clients, and known offensive-distro markers) and
|
||||
**`source.ip` is populated**. It is meant to highlight **credential access** where the client fingerprint does not look
|
||||
like routine kubectl or well-known controller traffic relative to your environment.
|
||||
|
||||
### Possible investigation steps
|
||||
|
||||
- Tie `user.name` (and `kubernetes.audit.impersonatedUser.*` if present) to a human, service account, or cloud identity
|
||||
and validate whether that principal should use this user-agent profile against the targeted namespaces and secret names.
|
||||
- Review `kubernetes.audit.objectRef.namespace` and `kubernetes.audit.objectRef.name` for high-value objects (service
|
||||
account tokens, cloud IAM bindings, registry pulls, TLS bundles).
|
||||
- Pivot on `source.ip` in VPC flow, VPN, or proxy logs to determine origin (employee laptop, compromised host, cloud
|
||||
instance) and correlate with other API bursts or exec activity.
|
||||
- Check `kubernetes.audit.annotations.authorization_k8s_io/decision` for successful reads versus failed probing.
|
||||
|
||||
### False positive analysis
|
||||
|
||||
- CI, GitOps, or one-off scripts can emit generic user agents with broad RBAC; exclude stable pipelines and service
|
||||
accounts after review.
|
||||
- Local API server loopback may still populate `source.ip` in some topologies; compare with expected control-plane paths.
|
||||
|
||||
### Response and remediation
|
||||
|
||||
- If unauthorized, rotate affected secrets and credentials, revoke tokens or kubeconfigs for the identity, tighten RBAC,
|
||||
and block or isolate the source host at the network edge to the API server where appropriate.
|
||||
"""
|
||||
references = [
|
||||
"https://attack.mitre.org/techniques/T1552/007/",
|
||||
"https://kubernetes.io/docs/concepts/configuration/secret/",
|
||||
]
|
||||
risk_score = 73
|
||||
rule_id = "a4c8e901-2b7f-4d6e-9a3c-8e1f0d5b6c2a"
|
||||
severity = "high"
|
||||
tags = [
|
||||
"Data Source: Kubernetes",
|
||||
"Domain: Kubernetes",
|
||||
"Use Case: Threat Detection",
|
||||
"Tactic: Credential Access",
|
||||
"Resources: Investigation Guide",
|
||||
]
|
||||
timestamp_override = "event.ingested"
|
||||
type = "query"
|
||||
query = '''
|
||||
data_stream.dataset:"kubernetes.audit_logs" and
|
||||
event.action:(get or list) and
|
||||
kubernetes.audit.objectRef.resource:"secrets" and
|
||||
user_agent.original:(curl* or python* or Python* or wget* or Go-http* or perl* or java* or node* or php* or *distrib#kali* or *kali-amd64 or *kali-arm64*) and
|
||||
source.ip:*
|
||||
'''
|
||||
|
||||
[[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