From b981fb0ffec337e94af479e84eadef47642d6f24 Mon Sep 17 00:00:00 2001 From: Samirbous <64742097+Samirbous@users.noreply.github.com> Date: Wed, 22 Apr 2026 23:18:39 +0100 Subject: [PATCH 1/3] [New] Kubernetes Secret get or list via Scripting or Generic HTTP Client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- ..._secret_access_scripting_http_clients.toml | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml diff --git a/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml b/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml new file mode 100644 index 00000000000..698413c0146 --- /dev/null +++ b/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml @@ -0,0 +1,99 @@ +[metadata] +creation_date = "2026/04/22" +integration = ["kubernetes"] +maturity = "production" +updated_date = "2026/04/22" + +[rule] +author = ["Elastic"] +description = """ +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). +""" +false_positives = [ + """ + Administrators and SREs sometimes use curl or Python from a workstation or jump host to debug Secret content during + incidents; confirm identity, IP, and change records before escalating. + """, + """ + Custom internal tools built with Go, Java, Node, or Python may legitimately read secrets with matching user-agent + substrings; baseline known automation and exclude stable service accounts or namespaces. + """, +] +index = ["logs-kubernetes.audit_logs-*"] +language = "kuery" +license = "Elastic License v2" +name = "Kubernetes Secret get or list via Scripting or Generic HTTP Client" +note = """## Triage and analysis + +### Investigating Kubernetes Secret get or list via Scripting or Generic HTTP Client + +The rule matches Kubernetes audit events for **secret** `get`/`list` where `user_agent.original` resembles **curl, +wget, Python, Perl, Java, Node, PHP**, or **Go’s default HTTP client**, and **`source.ip` is populated**. Use it to spot +manual or scripted **credential access** that bypasses standard cluster tooling. + +### 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 client class 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 runners and GitOps jobs occasionally use curl or generic Go clients with broad RBAC; exclude stable pipelines 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 wget* or Go-http* or perl* or java* or node* or php*) 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/" From a473ce458522958c866e901226dddeec113753ab Mon Sep 17 00:00:00 2001 From: Samirbous <64742097+Samirbous@users.noreply.github.com> Date: Wed, 22 Apr 2026 23:32:58 +0100 Subject: [PATCH 2/3] ++ --- ..._secret_access_scripting_http_clients.toml | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml b/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml index 698413c0146..59b704049fa 100644 --- a/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml +++ b/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml @@ -7,38 +7,38 @@ updated_date = "2026/04/22" [rule] author = ["Elastic"] description = """ -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). +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 = [ """ - Administrators and SREs sometimes use curl or Python from a workstation or jump host to debug Secret content during - incidents; confirm identity, IP, and change records before escalating. + 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. """, """ - Custom internal tools built with Go, Java, Node, or Python may legitimately read secrets with matching user-agent - substrings; baseline known automation and exclude stable service accounts or namespaces. + 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 via Scripting or Generic HTTP Client" +name = "Kubernetes Secret get or list with Suspicious User Agent" note = """## Triage and analysis -### Investigating Kubernetes Secret get or list via Scripting or Generic HTTP Client +### Investigating Kubernetes Secret get or list with Suspicious User Agent -The rule matches Kubernetes audit events for **secret** `get`/`list` where `user_agent.original` resembles **curl, -wget, Python, Perl, Java, Node, PHP**, or **Go’s default HTTP client**, and **`source.ip` is populated**. Use it to spot -manual or scripted **credential access** that bypasses standard cluster tooling. +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 client class against the targeted namespaces and secret names. + 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 @@ -47,8 +47,8 @@ manual or scripted **credential access** that bypasses standard cluster tooling. ### False positive analysis -- CI runners and GitOps jobs occasionally use curl or generic Go clients with broad RBAC; exclude stable pipelines after - review. +- 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 @@ -76,7 +76,7 @@ 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 wget* or Go-http* or perl* or java* or node* or php*) and +user_agent.original:(curl* 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:* ''' From c641b78eb6a3922d0866879c5dcbf377f18550fc Mon Sep 17 00:00:00 2001 From: Samirbous <64742097+Samirbous@users.noreply.github.com> Date: Fri, 1 May 2026 12:38:59 +0100 Subject: [PATCH 3/3] Update credential_access_kubernetes_secret_access_scripting_http_clients.toml --- ..._access_kubernetes_secret_access_scripting_http_clients.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml b/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml index 59b704049fa..afcdc57d591 100644 --- a/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml +++ b/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml @@ -76,7 +76,7 @@ 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 wget* or Go-http* or perl* or java* or node* or php* or *distrib#kali* or *kali-amd64 or *kali-arm64*) 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:* '''