Containers are standard units of software that package code and its related dependencies to enable applications to run reliably in different computing environments. Container images are lightweight executable packages of software that include all the elements necessary to run an application, including code, system tools, system libraries, settings, and runtime. At runtime, container images become containers, and they always run the same way, regardless of which infrastructure they run on. Kubernetes, an open-source container orchestration system, automates software deployment, scaling, and management. These two technologies are essential for building cloud-native apps or modernizing legacy applications. It is important to understand, however, that when you use a container image it is a template, and everything inside that image is contained in the container that is the running instance of that template. If your container image has dangerous capabilities, every running container using that image will as well.
You can significantly improve the security of Linux systems and applications by using hardening measures. One hardening measure is Linux capabilities, which are supported by the Linux kernel. If you go to the Docker documentation, you can search for "Linux capabilities" and see every option you can add or remove related to Linux capabilities. Typically, the root user, or any ID with an UID of 0, gets specific privileges when running processes. When seeing the root user, the kernel and applications typically do not restrict access to activities. The root user has broad permission to do almost anything. The Linux capabilities are a subset of available root privileges to a process, which divides root privileges into smaller units. Each unit can be independently granted access to processes. When you adjust these capabilities independently, you can limit access to the complete set of privileges, which helps you decrease your security risk.
You define Linux capabilities in a header file called capability.h, and recent Linux versions support nearly forty capabilities. A few of the available capabilities include:
CAP_CHOWN: Enables the privilege to change the owner of a file. Once granted, CAP_CHOWN applies to any file in a local file system. A file has both an owning user and an owning group.
CAP_PERFMON: employ performance monitoring mechanisms.
CAP_SYS_TIME: ability to set the system time on a machine.
CAP_SYS_ADMIN: this is an overloaded capability that performs a wide range of administration operations, syslog operations, and many more.
Sometimes you may need to add capabilities to get a container to run, but when you do, you also need to think through what it means to add that capability to a container. The idea here is that you should not run a container with capabilities you do not need. The more capabilities you have, the more exposed you are to potential attacks.
In my video, I show a card cluster running locally. I have the deploy.yaml file, and in my deploy.yaml file there is a busybox running with some high privilege capabilities. I am just deploying it as is with these elevated privileges.
In my local cluster, I have an Insights agent running, which will send a report to Fairwinds Insights. In Insights, I navigate to Action Items. Then I choose my cluster and filter by title to find containers with dangerous capabilities. In the results, I can see my busybox container. So, Insights is reporting that this container has a dangerous capability. It also provides details about what the problem is and outlines remediation steps for how to fix that issue right in your workload configuration. You can remove the high privilege capability by editing securityContext.capabilities.
Let's go to the file. Instead of adding privileges, I am going to add the instruction "drop." Then I save this file, delete my pod, and deploy it again with the updated capabilities. The pod will start running again pretty quickly. Let's wait a little bit until the Insights agent sends a new report to the Insights dashboard. This information in this Action Items report is provided by Polaris, our open source policy engine for Kubernetes.
- name: payment
- Drop all capabilities from a pod as above
- Add only those required
- Run a comprehensive test suite to ensure security extensions have not blocked functionality that your containers or pods require
Now we can filter the cluster again for dangerous capabilities. You can see now that the Action Item is gone because I fixed the container, so it no longer had any dangerous capabilities enabled. Insights can help you find containers running with dangerous capabilities, advise you on how to remediate those issues, and then check again after you have taken corrective action to make sure that you are not leaving your containers open to exploitation.
If you want to try this out yourself but you are new to Fairwinds Insights, read this post that outlines how to get started (try our free tier for environments up to 20 nodes, two clusters, and one repo — sign up now). If you are already a Fairwinds Insights user, you can log in to the user interface (UI) to review your Action Items and see whether you have any containers running with dangerous capabilities.
Watch my short video about avoiding dangerous capabilities in containers.