25

When I run a container as a normal user I can map and modify directories owned by root on my host filesystem. This seems to be a big security hole. For example I can do the following:

$ docker run -it --rm -v /bin:/tmp/a debian
root@14da9657acc7:/# cd /tmp/a
root@f2547c755c14:/tmp/a# mv df df.orig
root@f2547c755c14:/tmp/a# cp ls df
root@f2547c755c14:/tmp/a# exit

Now my host filesystem will execute the ls command when df is typed (mostly harmless example). I cannot believe that this is the desired behavior, but it is happening in my system (debian stretch). The docker command has normal permissions (755, not setuid).

What am I missing?

Maybe it is good to clarify a bit more. I am not at the moment interested in what the container itself does or can do, nor am I concerned with the root access inside the container.

Rather I notice that anyone on my system that can run a docker container can use it to gain root access to my host system and read/write as root whatever they want: effectively giving all users root access. That is obviously not what I want. How to prevent this?

Sjaak Dalens
  • 390
  • 1
  • 3
  • 7

3 Answers3

13

There are many Docker security features available to help with Docker security issues. The specific one that will help you is User Namespaces.

Basically you need to enable User Namespaces on the host machine with the Docker daemon stopped beforehand:

dockerd --userns-remap=default &

Note this will forbid the container from running in privileged mode (a good thing from a security standpoint) and restart the Docker daemon (it should be stopped before performing this command). When you enter the Docker container, you can restrict it to the current non-privileged user:

docker run -it --rm -v /bin:/tmp/a --user UID:GID debian

Regardless, try to enter the Docker container afterwards with your default command of

docker run -it --rm -v /bin:/tmp/a debian

If you attempt to manipulate the host filesystem that was mapped into a Docker volume (in this case /bin) where files and directories are owned by root, then you will receive a Permission denied error. This proves that User Namespaces provide the security functionality you are looking for.

I recommend going through the Docker lab on this security feature at https://github.com/docker/labs/tree/master/security/userns. I have done all of the labs and opened Issues and PRs there to ensure the integrity of the labs there and can vouch for them.

Matthew Schuchard
  • 25,172
  • 3
  • 47
  • 67
  • 3
    But a regular user on my hosts system, I **can** run (for example) the standard debian image and that **will** give me root access to the **host**. The lab says "However, it also presents potential security risks." That is rather an understatement. Shouldn't it say: never ever run docker in this way because it gives all your users root access to the host system. – Sjaak Dalens Feb 02 '17 at 15:08
  • 3
    Thanks. It is now clear that I should not allow any regular user to run docker, but rather do that for them. The lab pointer is also useful. – Sjaak Dalens Feb 02 '17 at 15:54
  • Is it easy for a non-admin user to override this, or do you think it's a fairly safe way of securing the install? – BSUK Apr 01 '19 at 15:03
  • @BSUK It would need to be someone with root, or someone with elevated permissions for Docker and services on the host machine. – Matthew Schuchard Apr 01 '19 at 16:46
  • Is it possible to block access that a user does not have on the host (e.g. writing to bind-mounted /bin) and still allow access that a user has on the host (e.g. writing to bind-mounted home directory)? – Joshua Chia Jul 15 '21 at 02:07
8

Access to run docker commands on a host is access to root on that host. This is the design of the tool since the functionality to mount filesystems and isolate an application requires root capabilities on linux. The security vulnerability here is any sysadmin that grants access to users to run docker commands that they wouldn't otherwise trust with root access on that host. Adding users to the docker group should therefore be done with care.

I still see Docker as a security improvement when used correctly, since applications run inside a container are restricted from what they can do to the host. The ability to cause damage is given with explicit options to running the container, like mounting the root filesystem as a rw volume, direct access to devices, or adding capabilities to root that permit escaping the namespace. Barring the explicit creation of those security holes, an application run inside a container has much less access than it would if it was run outside of the container.

If you still want to try locking down users with access to docker, there are some additional security features. User namespacing is one of those which prevents root inside of the container from having root access on the host. There's also interlock which allows you to limit the commands available per user.

BMitch
  • 231,797
  • 42
  • 475
  • 450
  • 1
    It is clearly my misunderstanding of the concept. Thanks. – Sjaak Dalens Feb 02 '17 at 15:50
  • But if I'm allowed to create and run docker containers because my job requires me to, I can run them with docker user `root` and mount folders like /etc to the container. I can then access the files in that folder with host's `root` privileges. I've just tried it, editing a file in `/etc` on the host without using `sudo`. It works. I can edit the file directly from within the docker container or change the permissions and edit it on the host with only normal user privileges. Where's my misconception? – Hendrik Wiese May 07 '19 at 07:16
  • @HendrikWiese dockerd is running as root, so if you have direct API access as a user to a daemon running as root, you have root access. That API access is not a normal user privilege. – BMitch May 07 '19 at 10:19
  • @HendrikWiese the situation requiring you to run docker containers on a host requires root access. Docker is not a virtualization platform, it is a process container. Also the `docker` command is not user space, it is (by default) requiring sudo. – Petri Sirkkala Feb 06 '20 at 11:36
2

You're missing that containers run as uid 0 internally by default. So this is expected. If you want to restrict the permission more inside the container, build it with a USER statement in Dockerfile. This will setuid to the named user at runtime, instead of running as root.

Note that the uid of this user it not necessarily predictable, as it is assigned inside the image you build, and it won't necessarily map to anything on the outside system. However, the point is, it won't be root.

Refer to Dockerfile reference for more information.

Dan Lowe
  • 51,713
  • 20
  • 123
  • 112
  • 1
    I know that inside the container I run as uid 0. That's fine. But if I map /bin (or even /) from the host system onto some directory in the container, I have root access to the host file system and can access and modify anything. So my commands inside the container modify the outside filesystem as root. – Sjaak Dalens Feb 02 '17 at 06:41
  • 1
    @SjaakDalens I"m not sure what your goal is, but you have various options. Map the volume as read only, build the image to use an unprivileged user... – Dan Lowe Feb 02 '17 at 13:32