Container and Resource Discovery
This detection identifies adversaries performing container and resource discovery within Docker and Kubernetes environments. Attackers who gain initial access to a container or cluster node often enumerate running containers, pods, services, nodes, namespaces, and cluster configuration to understand the environment and plan lateral movement. Common methods include executing Docker CLI commands (docker ps, docker inspect, docker images), Kubernetes CLI commands (kubectl get pods/nodes/namespaces/services), querying the Docker daemon socket or Kubernetes API server programmatically, scanning for kubelets with tools like masscan, and using offensive tools such as Peirates. Detection focuses on process execution of enumeration commands—especially from unexpected parent processes, non-administrative accounts, or container contexts—as well as anomalous API query patterns against the Kubernetes API server.
What is T1613 Container and Resource Discovery?
Container and Resource Discovery (T1613) maps to the Discovery tactic — the adversary is trying to figure out your environment in MITRE ATT&CK.
This page provides production-ready detection logic for Container and Resource Discovery, covering the data sources and telemetry it touches: Microsoft Defender for Endpoint. The queries below are rated medium severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Tactic
- Discovery
- Technique
- T1613 Container and Resource Discovery
- Canonical reference
- https://attack.mitre.org/techniques/T1613/
let ContainerDiscoveryCommands = dynamic(["docker ps", "docker inspect", "docker images", "docker info", "docker stats", "docker network ls", "docker volume ls", "docker container ls"]);
let KubeDiscoveryPatterns = dynamic(["get pods", "get nodes", "get namespaces", "get services", "get deployments", "get secrets", "get configmaps", "describe pod", "describe node", "cluster-info", "get all", "get sa", "get serviceaccount"]);
let CrictlCommands = dynamic(["crictl ps", "crictl pods", "crictl images", "crictl info"]);
let SuspiciousParents = dynamic(["bash", "sh", "dash", "zsh", "python", "python3", "perl", "ruby", "nc", "ncat", "socat"]);
DeviceProcessEvents
| where TimeGenerated > ago(1d)
| where (
// Docker enumeration commands
(ProcessCommandLine has "docker" and (
ProcessCommandLine has "ps" or
ProcessCommandLine has "inspect" or
ProcessCommandLine has "images" or
ProcessCommandLine has "info" or
ProcessCommandLine has "stats" or
ProcessCommandLine has "network ls" or
ProcessCommandLine has "volume ls" or
ProcessCommandLine has "container ls"
))
or
// kubectl enumeration
(FileName =~ "kubectl" and (
ProcessCommandLine has "get pods" or
ProcessCommandLine has "get nodes" or
ProcessCommandLine has "get namespaces" or
ProcessCommandLine has "get services" or
ProcessCommandLine has "get deployments" or
ProcessCommandLine has "get secrets" or
ProcessCommandLine has "get configmaps" or
ProcessCommandLine has "get all" or
ProcessCommandLine has "cluster-info" or
ProcessCommandLine has "describe" or
ProcessCommandLine has "get sa" or
ProcessCommandLine has "get serviceaccount"
))
or
// crictl (containerd CLI) enumeration
(FileName =~ "crictl" and (
ProcessCommandLine has "ps" or
ProcessCommandLine has "pods" or
ProcessCommandLine has "images" or
ProcessCommandLine has "info"
))
or
// ctr (containerd) enumeration
(FileName =~ "ctr" and (
ProcessCommandLine has "containers list" or
ProcessCommandLine has "images list" or
ProcessCommandLine has "tasks list"
))
or
// Peirates and similar offensive tools
(FileName =~ "peirates")
or
// curl/wget against Docker socket or Kubernetes API
((FileName in~ ("curl", "wget")) and (
ProcessCommandLine has "/var/run/docker.sock" or
ProcessCommandLine has ":8080/api" or
ProcessCommandLine has ":6443/api" or
ProcessCommandLine has ":10250" or
ProcessCommandLine has "/api/v1/pods" or
ProcessCommandLine has "/api/v1/nodes" or
ProcessCommandLine has "/api/v1/namespaces"
))
)
| extend RiskScore = case(
InitiatingProcessFileName in~ (SuspiciousParents), 80,
AccountName !in~ ("root", "system") and FileName =~ "kubectl", 60,
ProcessCommandLine has "get secrets", 90,
ProcessCommandLine has "/var/run/docker.sock", 85,
ProcessCommandLine has ":10250", 80,
40
)
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, RiskScore
| where RiskScore >= 40
| order by RiskScore desc, TimeGenerated desc Detects process execution of Docker, kubectl, crictl, and ctr enumeration commands used to discover containers, pods, nodes, namespaces, services, secrets, and cluster configuration. Also detects curl/wget queries against the Docker Unix socket or Kubernetes API endpoints (including the kubelet API on port 10250). Assigns risk scores based on parent process suspiciousness, sensitive resource types (secrets), and direct socket/API access.
Data Sources
Required Tables
False Positives
- Legitimate DevOps engineers and SREs routinely run kubectl get pods/nodes and docker ps for operational monitoring and troubleshooting
- CI/CD pipeline agents (Jenkins, GitLab Runner, GitHub Actions self-hosted) execute container enumeration commands as part of automated build, test, and deploy workflows
- Kubernetes operators, admission controllers, and monitoring tools (Prometheus node-exporter, Datadog agent, Falco) query the kubelet API and Kubernetes API server continuously for health data
- Container security scanners (Trivy, Anchore, Snyk) enumerate images and running containers during scheduled vulnerability assessments
Sigma rule & cross-platform mapping
The detection logic for Container and Resource Discovery (T1613) above is provided in a vendor-neutral
form so you can deploy it on any SIEM. The same logic is shipped here as native
KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the
following logsource:
logsource:
category: process_creation
product: windows Browse the community-maintained Sigma rules for this technique:
Platform-specific guides for T1613
References (6)
- https://attack.mitre.org/techniques/T1613/
- https://docs.docker.com/engine/api/v1.41/
- https://kubernetes.io/docs/reference/kubernetes-api/
- https://unit42.paloaltonetworks.com/hildegard-malware-teamtnt/
- https://github.com/inguardians/peirates
- https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Docker Container Enumeration via CLI
Expected signal: Linux auditd execve syscall events or Sysmon EventCode=1 (ProcessCreate) showing docker binary executions with arguments: ps, images, network ls, volume ls, info, inspect. Parent process will be the invoking shell.
- Test 2Kubernetes Cluster Enumeration via kubectl
Expected signal: Process creation events showing kubectl binary with arguments: get nodes, get pods, get namespaces, get services, get deployments, get serviceaccounts, cluster-info, get clusterrolebindings, auth can-i. Multiple events in rapid succession.
- Test 3Kubernetes Secrets Enumeration via kubectl and Direct API
Expected signal: Process creation events for kubectl with 'get secrets' argument (risk score 90 in detection). If curl is used: process creation for curl with Kubernetes API URL pattern and bearer token in command line. In-container token file access may also appear in auditd open/read syscall logs.
Unlock Pro Content
Get the full detection package for T1613 including response playbook, investigation guide, and atomic red team tests.