Common container misconfigurations and how to prevent them
Docker is a containerization software that comes with a great set of features that make it easy to build and run containers. With the great features Docker provides, there are great possibilities for things to go wrong as well.
This article provides an overview of common container misconfigurations when using docker and tips to prevent them.
Use of root user account in containers
Docker images are usually built by writing all the build instructions in a configuration file named Dockerfile. When a container is started from these docker images, a root account will be available within the container by default. Even though these root accounts on the docker containers do not come with all the capabilities that a Linux root user has, it is recommended to use a non root user within a container.
The following excerpt shows that the default alpine image provides a root user within a container.
|$ docker run -it alpine sh |
/ # id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
One way to prevent accessing the container as a root user is to use the –user flag when spinning up a container.
|$ docker run -it –user 1001:1001 alpine sh |
/ $ id
As we can notice in the preceding excerpt, we got a shell as a non root user within the container.
Use of outdated, vulnerable and backdoored images
Docker images are typically downloaded from public repositories such as Docker Hub or private repositories setup inhouse. Taking Docker Hub as an example, anybody with a free account on Docker Hub can upload their images into this public repository. So it is possible that these Docker images which are being uploaded by the registered users can have publicly known vulnerabilities that could be intentional or unintentional.
These vulnerabilities can potentially provide an attacker foothold on our containers and the hosts where Docker is being run. It is recommended to download images only from verified publishers and with a tag known to be free from unpatched vulnerabilities.
Unwanted users being part of docker group
Users who are part of the docker group can perform privilege escalation attacks to become root. It is important to note that docker daemon requires root privileges to perform some of its operations and thus docker daemon runs with root privileges. So, if a user is part of docker group, it is possible to elevate his privileges to root.
Since docker requires root, you can easily get root access, if you are part of the docker group. So essentially if a malicious user is on a host with low privileges but can’t run commands with root privileges, being part of the docker group will give him/her the ability to become root. The following excerpt shows that the current user is part of Docker group and thus it is possible to elevate his privileges to root.
|$ id |
uid=1000(docker) gid=1000(docker) groups=1000(docker),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),131(lxd),132(sambashare)
So, it is recommended to review which users are part of Docker group as they can potentially become root users. The following command can be used to check the list of users part of this group.
|$ getent group docker |
Mounting docker.sock onto the containers
Docker socket is a UNIX socket that acts as a backbone for managing containers. When we type any Docker commands using the docker-cli client, the docker cli client is interacting with docker daemon using this UNIX socket. While this socket can be exposed over the network on a specific port to run docker commands remotely, communication using the UNIX socket is the default setting.
When we are starting a container and we want to manage other containers from that container, access to docker UNIX socket (/var/run/docker.sock) is required. It should be noted that a compromised container with /var/run/docker.sock mounted will give an attacker the ability to escape the container and gain access to the underlying host. So, it is recommended to avoid using docker.sock on the containers whenever possible.
Mounting sensitive host files or directories onto the containers
Docker provides a way to mount files and directories of the host machine onto the containers. This can be dangerous depending on what files or folders from the host are mounted onto the container. The following excerpt shows how files or directories can be mounted onto the containers.
|$ docker run -it -v /:/host alpine sh|
As we can notice in the preceding command, the host’s root file system is mounted onto the container. Anyone with access to the container can access any file on the host in this case. So, it is recommended to avoid mounting sensitive directories from the host onto the containers.
Use of –privileged flag
Docker provides a powerful feature called –privileged flag, which can be used when spinning up containers. When –privileged flag is used with a container, it will give all Linux capabilities to the container and thus if an attacker gains access to the container he/she can take advantage of these capabilities to be able to escape the container and gain control on the underlying host, where the container is running.
So, it is recommended to avoid using –privileged flag whenever possible.
Exposing Docker Daemon over HTTP
Docker Remote API is a feature that allows administrators to expose Docker daemon over HTTP. Using Docker remote API feature, users will be able to remotely interact with the Docker daemon using a REST API, which means we can perform a variety of operations such as listing images and running containers remotely over the network. We will even be able to start and stop containers remotely using this REST API. So this is a very powerful feature. On a default Docker setup this REST API is not exposed over the network. If this Docker remote API is exposed and if an attacker gains access to this Docker remote API, he will be able to gain full control on the host where Docker daemon is running.
As we discussed earlier, Docker requires root privileges to operate. So even using this Docker remote API attackers will be able to elevate their privileges to root remotely over the network. When Docker remote API is enabled, no authentication is required by default. That means the REST API is exposed to anyone in your network and they don’t have to authenticate to be able to interact with your containers. So, it is highly recommended to avoid exposing Docker daemon over the network. If it is required to be exposed, use appropriate authentication and SSL/TLS.
Unprotected Docker secrets
Secrets management is one of the challenges in any software. When it comes to Docker it is seen that secrets are kept in places such as environment variables and within the source code itself. It is recommended to avoid placing secrets in such places as these secrets will be bundled in the image being built and anyone with access to the docker image can obtain the secrets.
In addition to it, accessing environment variables from within the container will also leak these secrets.
Docker without a doubt is a powerful utility to containerize applications. With great power comes great responsibility. It is easy to make mistakes when spinning up Docker containers and small mistakes can lead to a great deal of damage.
It is worth taking time to better understand the common misconfigurations shown in the article and assess the security posture of your docker infrastructure.