English Portuguese

Preventing Docker Escaping Attacks

In my last post "Docker for Automating Honeypots or Malware Sandboxes" some people were worried about Docker not being safe enough to use it as a malware sandbox, at least for now, given for example the article From webshell to docker container escape with DVWA and dirtyc0w. The article speaks for itself, and containers are not replacements for Virtual Machines, which provide a better isolation. However I'd like to discuss 2 protection mechanisms that you could apply to protect attackers that can execute arbitrary code in the container:

1) Run the container as non-root user

Unless modified, by default User IDs (UIDs) are mapped directly from host to container, thus a root user in the container has the same capabilities in the host. It becomes notorious when there is a shared volume:

# First we create a secret file in the host
# And change its permission to be read only from root
$ sudo su
root$ mkdir -p /home/anderson/deleteme
root$ echo 'secret!' > /home/anderson/deleteme/secret_file
root$ chmod 600 /home/anderson/deleteme/secret_file
# [ Back to normal user ]

# Then we start a container sharing that directory (deleteme)
$ docker run --detach --name hackme -v $(pwd)/deleteme:/deleteme ubuntu sleep 2000

# And we try to access secret from inside the container
$ docker exec -it hackme bash
root@883384cec818:/$ cd /deleteme/
root@883384cec818:/deleteme$ ls -lah
total 20
drwxr-xr-x  2 1000 1000 4096 Jan 23 11:48 .
drwxr-xr-x 33 root root 4096 Jan 23 11:49 ..
-rw-------  1 root root    8 Jan 23 11:48 secret_file
root@883384cec818:/deleteme$ cat secret_file 

# If we move another user, we can avoid it
# Let's try to use a 'normal user'
root@883384cec818:/deleteme$ adduser normal_user
root@883384cec818:/deleteme$ su - normal_user
normal_user@883384cec818:~$ cd /deleteme/
normal_user@883384cec818:/deleteme$ cat secret_file
cat: secret_file: Permission denied

You should also disable sudo. For Alpine images for example it comes without it by default.

2) Using a read-only file system:

It's common for attackers to create files after successfully exploiting systems. One control for that is to make the entire system read-only. You can apply the read-only (ro) flag for individual volumes as well, e.g., docker run (...) -v volumeOnHost:volumeOnContainer:ro (...).

# Create a new container, but read-only this time
$ docker run --detach --name hackme --read-only=true ubuntu sleep 2000

# Connect to this container and try to create a file
# Note: also changing {content,permissions}/removing existing files won't do
$ docker exec -it hackme bash
root@61ee2c744c4a:/$ touch some_file
touch: cannot touch 'some_file': Read-only file system

The drawback is that some applications still need to write temporary files. For that you can use a temporary filesystem without execution nor suid files, as pointed in this article:

# Starting container read-only, but with /etc w/ read&write, but no exec
$ docker run --detach --name hackme --read-only=true --tmpfs /etc:rw,noexec,nosuid,size=2g ubuntu sleep 2000

# Trying to create and execute a shell script from /etc
$ docker exec -it hackme bash
bash-4.3$ cd /etc
bash-4.3$ touch test
bash-4.3$ echo '#!/bin/bash' >> test
bash-4.3$ echo 'echo 1111111' >> test
bash-4.3$ chmod +x test
bash-4.3$ ls -lah test
-rwxr-xr-x 1 0 0 25 Jan 23 12:34 test
bash-4.3$ ./test
bash: ./test: Permission denied

That's all for today.

Thank you.

Share the knowledge :)

Share on Twitter Share on Facebook Share on Google Plus Share on LinkedIn Share on Hacker News