EXPLORE
← Back to Explore
elasticlowTTP

Direct Interactive Kubernetes API Request Detected via Defend for Containers

This rule detects the execution of direct interactive Kubernetes API requests inside a container. An adversary may need to execute direct interactive Kubernetes API requests to gain access to the Kubernetes API server or other resources within the cluster. These requests are often used to enumerate the Kubernetes API server or other resources within the cluster, and may indicate an attempt to move laterally within the cluster. Note that this rule may not trigger if the token is expanded within the process argument list, as the length of the "process.args" field may lead to the field being ignored.

MITRE ATT&CK

executiondiscoverylateral-movement

Detection Query

process where host.os.type == "linux" and event.type == "start" and event.action == "exec" and (
  (
    process.name == "curl" and
    process.args in ("-H", "--header") and
    process.args like "*Authorization: Bearer *" and
    (
      /* CA-specified */
      process.args in ("--cacert", "--capath") or
      /* insecure */
      process.args in ("-k", "--insecure")
    )
  ) or
  (
    process.name == "wget" and
    process.args like "--header*" and
    process.args like "*Authorization: Bearer *" and
    (
      /* CA-specified */
      process.args == "--ca-certificate" or
      /* insecure */
      process.args == "--no-check-certificate"
    )
  ) or
  (
    /* Account for tools that execute utilities as a subprocess, in this case the target utility name will appear as a process arg */
    process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "busybox") and
    process.args in ("wget", "/bin/wget", "/usr/bin/wget", "/usr/local/bin/wget") and
    process.args like "--header*" and
    process.args like "*Authorization: Bearer*" and
    process.args == "--no-check-certificate"
  ) or
  (
    /* ssl_client is busybox-specific, so we need to handle it separately */
    process.name == "busybox" and
    process.args == "ssl_client" and
    process.args like "*Authorization: Bearer*"
  ) or
  (process.name == "openssl" and process.args == "s_client" and process.args == "-connect") or
  (process.name == "socat" and process.args like~ "*ssl*") or
  (process.name == "ncat" and process.args like "--ssl*") or
  (process.name == "kubectl" and process.args in ("get", "list", "watch", "create", "patch", "update"))
) and
process.interactive == true and container.id like "*"

Author

Elastic

Created

2026/01/21

Data Sources

Elastic Defend for Containerslogs-cloud_defend.process*

Tags

Data Source: Elastic Defend for ContainersDomain: ContainerOS: LinuxUse Case: Threat DetectionTactic: ExecutionTactic: DiscoveryResources: Investigation Guide
Raw Content
[metadata]
creation_date = "2026/01/21"
integration = ["cloud_defend"]
maturity = "production"
min_stack_comments = "Defend for Containers integration was re-introduced in 9.3.0"
min_stack_version = "9.3.0"
updated_date = "2026/03/24"

[rule]
author = ["Elastic"]
description = """
This rule detects the execution of direct interactive Kubernetes API requests inside a container. An adversary may
need to execute direct interactive Kubernetes API requests to gain access to the Kubernetes API server or other resources
within the cluster. These requests are often used to enumerate the Kubernetes API server or other resources within the
cluster, and may indicate an attempt to move laterally within the cluster. Note that this rule may not trigger if the
token is expanded within the process argument list, as the length of the "process.args" field may lead to the field being
ignored.
"""
false_positives = [
    """
    There is a potential for false positives if the direct interactive Kubernetes API requests are used for legitimate purposes,
    such as debugging or troubleshooting. It is important to investigate any alerts generated by this rule to determine
    if they are indicative of malicious activity or part of legitimate container activity.
    """,
]
from = "now-6m"
index = ["logs-cloud_defend.process*"]
interval = "5m"
language = "eql"
license = "Elastic License v2"
name = "Direct Interactive Kubernetes API Request Detected via Defend for Containers"
note = """ ## Triage and analysis

> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

### Investigating Direct Interactive Kubernetes API Request Detected via Defend for Containers

The rule flags interactive use of curl, wget, openssl, busybox ssl_client, socat/ncat, or kubectl from inside a container to call the Kubernetes API with a bearer token, often with custom CA or insecure TLS options. An operator enumerates cluster resources and tests access with in-pod credentials, enabling lateral movement or privilege escalation; after landing in a pod, they read the service account token and query the API to list namespaces, pods, or secrets, or issue kubectl get/patch to probe or modify workloads.

### Possible investigation steps

- Map the container ID to its pod, namespace, node, image, and owning controller, and confirm whether this workload is expected to make direct Kubernetes API calls or allow interactive access.
- Determine how the interactive session was initiated and by whom by correlating with Kubernetes events and audit logs for exec/attach/ephemeral-container activity and runtime logs for TTY sessions, including the initiating principal and source IP.
- Correlate with API server audit logs to retrieve the exact requests (verbs, resources, namespaces), the authenticated subject (service account or user), and response codes to identify any successful access to sensitive resources like Secrets or workload-modifying actions.
- Inspect the pod for credential use and operator traces by checking recent process activity, shell history, environment variables, and access to service account token or kubeconfig files at expected mount paths.
- Assess scope and potential persistence by listing recent cluster objects created or modified by the same identity across namespaces (Pods, CronJobs, RoleBindings, Secrets) within the timeframe around the alert.

### False positive analysis

- An administrator used kubectl interactively within a maintenance container to run get/list/patch commands during routine operations such as inspecting pods or updating labels, which matches expected administrative behavior.
- A developer ran openssl s_client, socat with SSL, or ncat --ssl interactively from within the container to troubleshoot TLS connectivity to a service endpoint, not the Kubernetes API server, causing the rule to fire despite benign intent.

### Response and remediation

- Immediately delete the affected pod to terminate interactive access, and apply a temporary NetworkPolicy in its namespace that blocks egress to the default/kubernetes service (API server) while you patch its ServiceAccount to set automountServiceAccountToken: false.
- Use API server audit logs and kubectl to enumerate actions taken by the pod’s ServiceAccount and revert any unauthorized objects it created or modified (Pods, CronJobs, RoleBindings, Secrets), and remove any attached ephemeral containers across the namespace.
- Rotate credentials and restore workloads by deleting any legacy ServiceAccount token Secret, restarting pods to issue new bound tokens, rebuilding the image from a trusted base, and redeploying with read-only rootfs and minimal RBAC verified via kubectl auth can-i.
- Escalate to incident response if audit logs show Secrets access or create/patch/update on workloads, if the ServiceAccount holds cluster-admin, or if the observed commands used curl -k/--insecure, wget --no-check-certificate, or openssl/socat/ncat with SSL to the API server.
- Harden the cluster by enforcing admission controls that deny kubectl exec/attach for non-admins, requiring automountServiceAccountToken: false by default and short-lived bound tokens where needed, restricting NetworkPolicies so only designated controllers can reach the API server, and adopting distroless images that omit curl/wget/openssl/ncat.
"""
risk_score = 21
rule_id = "26a989d2-010e-4dae-b46b-689d03cc22b3"
severity = "low"
tags = [
    "Data Source: Elastic Defend for Containers",
    "Domain: Container",
    "OS: Linux",
    "Use Case: Threat Detection",
    "Tactic: Execution",
    "Tactic: Discovery",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where host.os.type == "linux" and event.type == "start" and event.action == "exec" and (
  (
    process.name == "curl" and
    process.args in ("-H", "--header") and
    process.args like "*Authorization: Bearer *" and
    (
      /* CA-specified */
      process.args in ("--cacert", "--capath") or
      /* insecure */
      process.args in ("-k", "--insecure")
    )
  ) or
  (
    process.name == "wget" and
    process.args like "--header*" and
    process.args like "*Authorization: Bearer *" and
    (
      /* CA-specified */
      process.args == "--ca-certificate" or
      /* insecure */
      process.args == "--no-check-certificate"
    )
  ) or
  (
    /* Account for tools that execute utilities as a subprocess, in this case the target utility name will appear as a process arg */
    process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "busybox") and
    process.args in ("wget", "/bin/wget", "/usr/bin/wget", "/usr/local/bin/wget") and
    process.args like "--header*" and
    process.args like "*Authorization: Bearer*" and
    process.args == "--no-check-certificate"
  ) or
  (
    /* ssl_client is busybox-specific, so we need to handle it separately */
    process.name == "busybox" and
    process.args == "ssl_client" and
    process.args like "*Authorization: Bearer*"
  ) or
  (process.name == "openssl" and process.args == "s_client" and process.args == "-connect") or
  (process.name == "socat" and process.args like~ "*ssl*") or
  (process.name == "ncat" and process.args like "--ssl*") or
  (process.name == "kubectl" and process.args in ("get", "list", "watch", "create", "patch", "update"))
) and
process.interactive == true and container.id like "*"
'''

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

[[rule.threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"

[[rule.threat.technique.subtechnique]]
id = "T1059.004"
name = "Unix Shell"
reference = "https://attack.mitre.org/techniques/T1059/004/"

[[rule.threat.technique]]
id = "T1609"
name = "Container Administration Command"
reference = "https://attack.mitre.org/techniques/T1609/"

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

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

[[rule.threat.technique]]
id = "T1613"
name = "Container and Resource Discovery"
reference = "https://attack.mitre.org/techniques/T1613/"

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

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

[[rule.threat.technique]]
id = "T1550"
name = "Use Alternate Authentication Material"
reference = "https://attack.mitre.org/techniques/T1550/"

[[rule.threat.technique.subtechnique]]
id = "T1550.001"
name = "Application Access Token"
reference = "https://attack.mitre.org/techniques/T1550/001/"

[rule.threat.tactic]
id = "TA0008"
name = "Lateral Movement"
reference = "https://attack.mitre.org/tactics/TA0008/"