Anyone who can reach a container API with enough permission can start their own workload inside your infrastructure, with whatever image, privileges and network access they choose. MITRE ATT&CK T1610 Deploy Container covers adversaries deploying a container to run malicious processes or to sidestep defences, for example a container without network policy or user limits, or a privileged container placed on a chosen node to set up T1611 Escape to Host. In ATT&CK v20 it sits in the Execution tactic (TA0002), applies to the Containers platform and has no sub-techniques. This guide is for detection engineers, platform and Kubernetes teams and cloud security owners: it covers the access paths at the level of the ATT&CK description, then detection logic across Kubernetes audit, container runtime and cloud logs, admission controls, the workload identity angle and response. It contains no attack procedures. For general cluster hardening, see the Kubernetes Security Guide.
Key takeaways
- The API is the attack surface. ATT&CK names Docker's
createandstartAPIs, the Kubernetes dashboard and Kubeflow as deployment routes; an exposed or over-permissive control plane is the usual cause. - Workload identities deploy too. In the Kubeflow attacks Microsoft reported, the attacker used a notebook's mounted service account to deploy new containers, so service account RBAC is a T1610 control.
- Admission control is the strongest prevention. Pod Security Admission at Baseline or Restricted, plus an image allowlist, blocks the privileged, host-namespace and unknown-image pods that make T1610 dangerous.
- Detect the chain. ATT&CK detection strategy DET0249 correlates container creation with an unapproved image or risky runtime attributes and the new container's first process or network connection.
- DaemonSets multiply impact. ATT&CK notes ReplicaSets and DaemonSets let one deployment place containers on many nodes at once, so treat new DaemonSets as high severity.
How the attack works
ATT&CK describes adversaries deploying containers "based on retrieved or built malicious images or from benign images that download and execute malicious payloads at runtime". The first case overlaps with T1204.003 Malicious Image and T1612 Build Image on Host; the second means image scanning alone will not catch it. Defenders can group the routes like this:
| Route | Typical precondition | Where it becomes visible |
|---|---|---|
| Docker Engine API | Daemon reachable over the network without TLS client authentication (Docker's default is a local UNIX socket); exposed TCP 2375 is the classic case | Docker daemon events container_create and container_start; remote calls to /containers/create |
| Kubernetes API server | Stolen kubeconfig, cloud IAM mapping to cluster-admin, a service account token with create on pods or workload controllers | Kubernetes audit log create on pods, deployments, daemonsets, jobs, cronjobs |
| Web consoles | Kubernetes dashboard, Kubeflow or another UI exposed with weak or no authentication | Audit events attributed to the console's service account; ingress logs |
| Kubelet and runtime on a node | Node access or an unauthenticated kubelet | containerd CRI CreateContainer and StartContainer; static pods that bypass the API server |
| CI/CD and GitOps | Compromised pipeline or Git credentials that the deployment controller trusts | Pipeline logs, Git commits to manifests, then normal audit events from the deployer identity |
ATT&CK v20 links T1610 to TeamTNT, Salt Typhoon and TeamPCP, to Kinsing, Doki and TeamPCP Cloud Stealer, and to the Kubernetes tool Peirates. Most observed use is cryptomining and credential theft, which is why T1496.001 Compute Hijacking and T1552.007 Container API often follow.
Where it shows up
- Exposed Docker hosts: worms that start a container on each open daemon, install a miner and steal cloud credentials, as TeamTNT did in 2020.
- Exposed ML and admin consoles: Kubeflow and Kubernetes dashboards published to the internet.
- Privileged pod for breakout: a pod with
privileged: true, host PID or network namespaces, or ahostPathmount of/, scheduled to a target node. - Persistence: a DaemonSet or CronJob (T1053.007 Container Orchestration Job) that recreates the attacker's container.
- Agentic botnets: the 2026 Carbonato botnet launched privileged containers with host access through unauthenticated Docker daemons on port 2375 and hunted AI API keys.
Detection
DET0249 "Behavior-chain detection for T1610 Deploy Container across Docker & Kubernetes control/node planes" has one analytic, AN0693: remote or API-driven creation and start of a container whose image is not on an allowlist (or uses the latest tag), by a non-admin principal, or with risky runtime attributes such as --privileged, host PID or network namespaces, sensitive host path mounts or added capabilities, correlated with the new container's activity. Its log sources map to concrete telemetry:
| Layer | Log source | Fields and events to use |
|---|---|---|
| Kubernetes control plane | API server audit log (EKS audit log type to CloudWatch log group /aws/eks/<cluster>/cluster, not enabled by default; GKE and AKS equivalents) | verb=create on pods and workload controllers; user.username, sourceIPs, userAgent; requestObject fields securityContext.privileged, hostPID, hostNetwork, volumes[].hostPath, image |
| Admission | Pod Security Admission audit and warn annotations; policy engine reports | Violations by namespace and requester, especially rejected privileged pods |
| Container runtime | Docker daemon events, containerd CRI | container_create, container_start, CreateContainer with privileged or host namespaces |
| Node and kernel | eBPF runtime sensor or auditd | First process and first outbound connection from a new container PID namespace |
| Cloud detection | Amazon GuardDuty EKS findings | Execution:Kubernetes/AnomalousBehavior.WorkloadDeployed, PrivilegeEscalation:Kubernetes/AnomalousBehavior.WorkloadDeployed!PrivilegedContainer, Persistence:Kubernetes/AnomalousBehavior.WorkloadDeployed!ContainerWithSensitiveMount |
Rules to build first
- Privileged or host-namespace pod created outside
kube-systemor an approved platform namespace, by any identity. - Service account creating workloads it has never created before, especially pods created by a token from a notebook, CI runner or application namespace. This is the Kubeflow pattern.
- New DaemonSet or a workload targeting a specific node with
nodeName, outside GitOps change. - Image outside the allowlist: registry not approved, digest not signed, or
latesttag in production namespaces. - Remote Docker API calls to
/containers/createfrom any address other than an approved management host; any listener on TCP 2375. - Anonymous access: GuardDuty
SuccessfulAnonymousAccessfindings or audit events fromsystem:anonymous.
Measuring it
- Admission coverage: share of namespaces with Pod Security Admission
enforceat Baseline or above. - Image provenance: percentage of running containers from approved registries with verified signatures.
- Exposure: count of Docker daemons, dashboards and API servers reachable from the internet (target zero unauthenticated).
- Audit coverage: clusters sending audit logs to the SIEM, with latency under 15 minutes.
- Workload creators: number of non-human identities with
createon pods or controllers, reviewed quarterly.
Prevention and hardening
ATT&CK lists four mitigations: M1047 Audit, M1035 Limit Access to Resource Over Network, M1030 Network Segmentation and M1018 User Account Management. In practice:
- Close the daemon: keep Docker on its local UNIX socket; where remote access is needed, Docker documents SSH or TLS with
tlsverifyand a trusted CA so only clients with signed certificates connect. See the Container Runtime Security Guide. - Private control plane: restrict API server endpoints to known networks and keep dashboards and ML consoles behind single sign-on.
- Pod Security Admission: label namespaces
pod-security.kubernetes.io/enforce: baselineorrestricted, starting withwarnandaudit. Baseline forbids privileged containers, host namespaces andhostPathvolumes; Restricted also requiresrunAsNonRoot,allowPrivilegeEscalation: falseand dropping all capabilities. - Image policy: an admission policy that allows only approved registries and signed digests. See the Kubernetes Admission Control Guide and the Container Registry Security Guide.
- RBAC: very few identities need
createon pods, DaemonSets or Jobs cluster-wide; bind deploy rights per namespace to the GitOps or CI identity. See the Kubernetes RBAC Guide. - Egress control: default-deny NetworkPolicy and node egress filtering stop runtime payload downloads and mining pool connections.
Rolling out admission controls
- Inventory namespaces and apply PSA
warnandauditat Baseline cluster-wide. - Review violations for two weeks; fix or document platform exceptions (CNI, logging agents, CSI drivers).
- Move
enforceto Baseline in a pilot ring of non-production namespaces, then production. - Add the image allowlist in audit mode, then enforce.
- Roll back by relabelling a namespace from
enforcetowarn; keep the change in Git so it is reviewed.
Where identity fits
Every T1610 deployment is an authorised API call from some identity. The ones to govern are non-human: Kubernetes service accounts, CI/CD deployer identities, cloud IAM roles mapped into the cluster and the console service accounts behind dashboards. The Kubeflow case shows the pattern: dashboard access led to code in a notebook, and the notebook's auto-mounted service account could deploy containers in its namespace. Disable token auto-mount where workloads do not call the API (automountServiceAccountToken: false), scope service account roles to what each workload needs, and alert when a workload identity creates pods. In the Tesla and TeamTNT cases, the deployed workload then reached cloud keys stored in a pod or in .aws files, which is why short-lived workload identity beats static keys. See the Kubernetes Service Account Token Guide and the Kubernetes NHI Security Guide.
Responding to a rogue container
- Contain without destroying evidence: isolate the pod with a deny-all NetworkPolicy and cordon the node before deleting anything. See the Container and Kubernetes Forensics Guide.
- Identify the deployer: from the audit event, record
user.username, groups, source IP and user agent; revoke that credential or service account token. - Find siblings: search for the same image digest, DaemonSets, CronJobs and static pods across all clusters.
- Rotate reachable secrets: any secret, cloud credential or token mounted in or reachable from the namespace or node.
- Close the entry point and follow the Kubernetes Cluster Compromise Playbook if cluster-admin was involved.
Lessons from incidents
- TeamTNT, 2020: a worm found Docker APIs without access control, started a container on each and read AWS CLI credential files; a mining pool page listed 119 compromised systems. See the TeamTNT worm breach analysis.
- Kubeflow, 2020: exposed dashboards let attackers deploy a mining image using the mounted service account, across tens of clusters. See the Kubeflow cryptomining analysis.
- Carbonato, 2026: an AI-agent botnet launched privileged containers through unauthenticated port 2375 daemons. See the Carbonato botnet analysis.
Common failure patterns
- Audit logs off: managed clusters with control plane audit logging never enabled, leaving no record of who created the workload.
- PSA left at Privileged: namespaces without labels default to no restriction.
- Over-broad service accounts: application or notebook accounts with
editon their namespace and auto-mounted tokens. - Scanning only at build: benign images that download payloads at runtime pass every registry scan.
- Exceptions that never expire: a privileged exception granted for one agent and reused by others.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| MITRE ATT&CK v20 | T1610; related T1611, T1612, T1204.003, T1053.007, T1552.007, T1496.001, T1613 | Technique and common preceding and following steps |
| ATT&CK mitigations | M1047, M1035, M1030, M1018 | Audit, network access limits, segmentation, account management |
| NIST SP 800-53 Rev. 5 | AC-3, AC-6, CM-7, CM-7(5), SC-7, SI-4, AU-6 | Access enforcement, least privilege and functionality, allowlisting, boundary protection, monitoring |
| NIST CSF 2.0 | PR.AA-05, PR.PS-01, PR.IR-01, DE.CM-09 | Least privilege, configuration management, protection from unauthorised access, monitoring |
| NIST SP 800-190 | Orchestrator and runtime countermeasures | See the NIST SP 800-190 Container Security Guide |
| CIS Controls v8.1 | Controls 2, 4, 6 and 8 | Software inventory, secure configuration, access control, audit logs |
Practitioner checklist
- Confirm no Docker daemon listens on TCP without TLS client authentication, and no dashboard is internet-facing.
- Enable Kubernetes audit logging on every cluster and forward it to the SIEM.
- Apply Pod Security Admission at Baseline or Restricted with a staged rollout.
- Enforce an image registry and signature allowlist at admission.
- Review every identity with
createon pods and workload controllers; disable unused token auto-mount. - Build the six rules above and test them with a benign privileged pod in a lab namespace.
- Apply default-deny egress for workload namespaces.
- Rehearse the rogue container response, including evidence capture before deletion.
Standards and references
- MITRE ATT&CK: Deploy Container (T1610)
- Kubernetes: Pod Security Standards
- Kubernetes: Auditing
- Docker: Protect the Docker daemon socket
- AWS: Send control plane logs to CloudWatch Logs (Amazon EKS)
- AWS: GuardDuty EKS protection finding types
- MITRE ATT&CK: Escape to Host (T1611)
- NIST: SP 800-53 Rev. 5 Security and Privacy Controls
Related NHI Mgmt Group resources: Kubernetes Security Guide · Kubernetes Audit Log Detection Guide · Container Security Guide · T1611 Escape to Host Defensive Guide · Kubernetes NHI Security Guide