This article summarizes the current security solutions for Docker containers. The solutions in this blog post have been discussed and designed by the Docker community. You can also find valuable tips on how to enhance security while running a Docker in a production environment.
Possible Security Issues in a container-based environment
Before we jump into the security solutions, let’s explore some security issues of container-based systems. Generally speaking, there are three types of attack models, which are caused by the vulnerabilities of the container-based systems.
Types of Attacks:
- Container compromise: result in illegitimate data access and affect control flow of instructions
- DoS(Deny of Services): disturb normal operation of the host or other container
- Privilege escalation: obtain a privilege which is not originally granted to the container
- Namespacing Issues -Docker containers utilize Kernel namespaces to provide a certain level of isolation. However, not all resources are namespaced:
- UID: Causing “root” user vulnerability
- Kernel keyring: containers running with a user of the same UID will have access to the same keys if they are handled by kernel keyring
- Kernel & its modules: Loaded modules become available across all containers and the host
- Devices: includes disk drives, sound-cards,GPU, etc.
- System time: The SYSTEM_TIME capability is disabled by default, but if it’s enabled, we will need to worry about it.
- Kernel Exploit – Container-based applications share the same host kernel, namely, flaws in the host kernel might allow malicious containers to escape and gain access over the over whole system.
- DoS Attacks – Since all containers share kernel resources, if a container or user consumes too much capacity of a certain resource, it will starve out other containers on the host.
- Container Breakout – Because users are not namespaced, any process that breaks out of the container will have the same privileges on the host as it did in the container. For example, if you were root in the container, you will be root on the host. It’s a typical privilege escalation attack , unlikely to happen, but possible.
- Poisoned Images – It’s possible for attackers to modify/embed malicious programs into the image and trick users to download such corrupt images
- Compromising secrets – Applications need credentials to access databases or backend services. An attacker who can get access to these credentials will also have the same access as the application. This problem becomes more acute in a microservice architecture in which containers are constantly stopping and starting.
Now Let’s take a look at what security solutions that come with the current Docker implementation and what strategies or techniques can be used in production.
One of the most important principles to achieve container security is Least Privileges: each process and container should run with the minimum set of access rights and resources it needs to perform its function. This includes the actions to reduce the capabilities of containers:
– Do not run processes in a container as root to avoid root access from attackers.
– Run filesystems as read-only so that attackers can not overwrite data or save malicious scripts to file.
– Cut down the kernel calls that a container can make to reduce the potential attack surface.
– Limit the resources that a container can use
This Least Privileges approach reduces the possibility that an attacker can access or exploit data or resources via a compromised container.
Internal Security Solutions
Containers can leverage the Linux Namespace and Control group to provide a certain level of isolation and resource limitation.
Docker provides process, filesystem, device, IPC and network isolations by using the related namespace.
- Process Isolation: Docker utilizes PID namespace to separate container processes from the host as well as other containers, so that processes in a container can’t observe or do anything to the other processes running in the host or in other containers.
- Filesystem Isolation: Use mount namespace to ensure that for each mount space, a container only have impact inside the container.
- Device Isolation: The container cannot access to any devices unless it’s privileged.
- IPC Isolation: Utilize IPC namespace to prevent the processes in a container from interfering with those in other containers.
- Network Isolation: Use network namespace so that each container has its own IP address, IP routing tables, network device, etc.
Docker employs Cgroup to control the amount of resources, such as CPU, memory, and disk I/O, that a container can use. Under this control, each container is guaranteed a fair share of the resources but preventing from consuming all of the available resources.
Linux Kernel Security Systems
The kernel security system is present to harden the security of a Linux host system. We can also use them to secure the host from containers.
By default, containers disable a large amount of Linux capabilities from its containers in order to prevent an attacker to damage the host system when a container is compromised. And it also allows configuration of capabilities that a container can use.
Linux Security Module (LSM)
Two most popular LSM will be AppArmor and SELinux:
- SELinux is a labeling system, that implements Mandatory access control using labels. Every object, such as process, file/directory, network ports, devices, etc, has a label. Rules are put in place to control the access to objects.
- AppArmor is a security enhancement model to Linux-based on Mandatory Access Control like SELinux. It permits the administrator to load a security profile into each program, which limits the capabilities of the program.
The Linux seccomp (secure computing mode) facility can be used to restrict the system calls that can be made by a process. namely, containers can be locked down to a specified set of system calls.
When running Docker in a production environment, you will want to leverage one of the security solutions listed above and apply proper precautions to provide a more secure and robust system. There are three major security tips in to keep in mind when running Docker in production.
Segregate Containers by Host
The main reason to place each user on a separate Docker Host is to minimize the loss when container breakout happens. If multiple users are sharing one host, if a user monopolizes all the memory on the host, it will starve out other users. Even worse, if container breakouts happen, a user could possibly gain access to another users’ containers or data through the compromised container.
Therefore, although this approach is less efficient than sharing hosts between users and will result in a higher number of VMs and/or machines than reusing hosts, it’s important for security.
Another similar solution would be separate containers with sensitive information from less-sensitive ones for the similar reason.
Just like what is recommended for Windows system, it’s recommended to apply updates regularly. This includes updating base images and dependent images to fix the vulnerabilities in common utilities and framework. At times, we need to update Docker daemon to gain access to new feature, security patches or bug fixes. Removing unsupported drivers is also important, because those could be a security risk since they won’t be receiving the same attention and updates as other parts of Docker.
To safely use images, you need to have guarantees about their provenance:
- where they came from
- who created them
- ensure you are getting the exactly the image you want
There are three solutions for image provenance: secure hash, secure signing and verification infrastructure and use Dockerfile properly.
- Secure Hash: Secure Hash is like a fingerprint for data. It’s a small string that is unique to given data. If you have a secure hash for some data and the data itself, you can recalculate the hash for the data then compare. In docker, it’s called docker digest, a SHA-256 hash of a filesystem layer or manifest (a metadata file describing the parts of an image, containing a list of constituent layer identified by digest)
- Secure Signing and Verification Infrastructure: Data could be changed / copied if it travels over unsecure channels (e.g. HTTP), so we need to ensure we are publishing and accessing content using secure protocols. Notary project is an ongoing secure signing and verification infrastructure project in docker, which compares a checksum for a downloaded file with the checksum in Notary’s trusted collection for the file source (e.g. docker.com). For more details, please check https://github.com/docker/notary
- Dockerfile: Not as we expected, dockerfile is likely to produce different images over time, so as time goes, it’s hard to be sure what is in your images. To use docker properly, you would:
- Always specify a tag in FROM instruction, and use digest to pull the exactly same image each time
- Provide version numbers when installing software from package managers. However, since package dependencies can change over time, sometime we need to use tools (e.g. aptly) to take a snapshot of the repository
- Verify any software or data downloaded from the internet by using checksums or cryptographic signatures.
This blog post is a glance of the current security solutions for docker containers, if you are interested, please refer to the reference articles for more details. Are you using Docker in production? Have you implemented some of these security models?