Containerization is a relatively new way to host and deploy applications in comparison to the traditional hardware-based deployment or VM-based virtualization. It’s fast, cost effective, and efficient. But is it secure?
Let’s find out.
The Concept of Containerization
While Docker and containers are the talk of the town in the DevOps world, the concept of containerization itself is not new. Chroot was introduced in Linux during the early 1980s to provide isolation. Unfortunately, due to weak implementation, chroot security was quickly broken via root access abuse.
Fast forward to today. OS-level virtualization via hypervisors and containers has come a long way in terms of both functionality and security. Containerization still isn’t foolproof when it comes to security. However, there is widespread use and support among many organizations, especially cloud service providers including Google, Microsoft, and Amazon.
What Is a Container?
Containers are lightweight virtualization mechanisms that run directly over a host operating system without the need for a guest operating system (unlike traditional virtualization which requires a separate guest OS for each virtualized instance). Containers leverage the same kernel on a central host OS by utilizing Linux namespaces. Some popular container products include Docker, CoreOS Rocket, VMWare ThinApp, and Canonical LXD. Docker is by far the most popular.
For the remainder of this post, I’ll refer to containers and Docker within the same context, unless specifically clarified.
Container Security Threats and Solutions
Escaping and privilege escalation
An attacker who gains access to a container may also be able to gain access to other containers or to the host itself. For example, a container may be able to access system directories on the host (via remounting) that are critical to security enforcement like cgroups, procfs, and sysfs. By default, users are not namespaced. Therefore, any process that breaks out of the container has the same privileges on the host as it does in the container.
If an attacker can get root inside a containerized app, (s)he can potentially gain root access to the host. This could also lead to potential privilege escalation attacks whereby a user gains elevated privileges, such as those of the root user, often through a bug in application code. This is the primary concern surrounding containers and—not surprisingly—a solution is not straightforward. Rather, it involves employing a comprehensive approach based on system hardening, strengthening default configurations, and patching.
Cross-container threats usually arise due to weak network defaults such as a bridge configuration. An application on one container may be able to compromise another container on the same host or on the same local network (e.g., gaining unauthorized access to the database container on the same host).
Container software, like any other software, must be up to date with security-related patches. Let’s take a look at an example of why this is critically important. To avoid root privilege abuse, Linux containers leverage a feature known as user namespace. This feature ensures root is a separate consideration across the container and the host via the use of uid and gid mappings. Interestingly, the user namespace wasn’t supported on Docker until version 1.10 release in February 2016. Be mindful that the user namespace is not enabled by default. If you’re still on an older version, be sure to patch your software.
If container images aren’t downloaded from trusted sources, there is a risk of downloading malicious images into the environment. To prevent this, always download images from a trusted source such as a local Docker Hub repository. Ensure that images include cryptographic guarantees and don’t contain any software with known vulnerabilities.
Denial of Service (DoS).
Denial of Service attacks may include scenarios where one container seizes control of all available system resources to stop other containers from operating properly. For example, generating a large number of requests to shared resources in order to exhaust memory, CPU, network, or storage.
The kernel is shared among all containers and the host (unlike VMs). This amplifies the impact of any vulnerabilities present in the kernel. Kernel exploits range from privilege escalation to arbitrary code execution, and even Denial of Service. Ensure the host operating system is hardened, up to date, and leverages kernel security patching features like grsecurity and PaX.
I recommend taking a comprehensive approach when securing containers. Start with a Docker configuration review using tools like Docker Bench. Many resources are available online to gauge container security. (e.g., Docker Security and CIS Docker Benchmark). Carefully review and implement the guidance provided as per your custom requirements. Some questions to consider during this process include:
- What is the primary use of the container?
- Who needs access?
- What are the access-level requirements?
- What actions are allowed (or forbidden)?
Next, perform threat models and penetration tests on the applications and the Docker environment itself. Finally, it is very important to note that leveraging the cloud, containers, and microservices do not prevent against traditional application security issues. A vulnerable application still poses risk to the whole environment.
No matter where you run an application, its vulnerabilities will follow.