In 2023, Airbus Protect demonstrated unparalleled achievements in cyber defence, marking a significant milestone for the company. Four key events in Germany contribute to the organisation's commitment to excellence and innovation in the ever-evolving landscape of cybersecurity.Read more
Container security: a beginner’s guide
What is Containerisation?
Containerisation – the practice of packaging software code and dependencies into a single ‘container’– has become the backbone of modern, cloud-native app development. Used in conjunction with other technologies like microservices, serverless architectures and DevOps, containerisation enables teams to quickly build, deploy, reconfigure and scale applications to run in any computing environment.
Containerisation is often used as an alternative to virtualisation – though containers can only host a single application, while virtual machines can host multiple apps. The appeal of containerisation hinges on the fact that, unlike a virtual machine, containers don’t need to include a guest OS in every instance. Instead, they can simply use the features and resources of the host OS.
In today’s fast-moving development environment, organisations should be prioritising container security throughout the development cycle, rather than treating it as an afterthought. With this guiding principle in mind, let’s take a whistlestop tour through container security best practices.
A quick note – in the interests of clarity, we’ll assume that you’re working with the Docker platform, as opposed to other solutions like containerd or Podman.
Securing your image
As you know, the basis of each container is a static file with executable code known as an image. In Docker, this is known as a Dockerfile. Each Dockerfile indicates which files are present in the container, which dependencies should be installed, which application should run, etc.
Illustration 1: Creation of a docker container
An interesting property of a Docker image is that it can be layered. This makes it possible to create additional images by stacking them – as illustrated below.
Illustration 2: Docker layering
Ensuring the security of your image is the first step in any container security strategy. This relies on a process known as image scanning – using vulnerability scanning tools to identify known vulnerabilities within containers and components.
Within Docker, the image scanning process typically includes the following steps:
- Checking the software packages, binaries, libraries, operative system files and more against databases of known vulnerabilities. Some Docker scanning tools have a repository containing the results for common images.
- Analysing the Dockerfile and image metadata to detect configurations which pose security concerns – such as running the app in privileged/root mode, leaving open ports exposed, including embedded user credentials, etc.
- Running user-defined policies. Organisations often have mandatory requirements for every image, such as checking for a list of blacklisted software, or ascertaining whether a SUID file has been set.
Once an image scan is complete, it’s a good idea to classify and group the various security issues. For some, it might be sufficient to simply include a warning notification. For others, the issue could be severe enough to justify aborting the build.
Securing your CI/CD pipeline
Containers are often deployed via a fully automated continuous integration and continuous deployment (CI/CD) pipeline. Not only does automating this process enable teams to work quickly, but it also ensures consistency and minimises human error.
To prevent a container with a large attack surface from being deployed, it’s a good idea to include an additional scan engine (synced with a vulnerability database) during the build phase of an image.
Kubernetes security: The control plane
Kubernetes is by far the most common container orchestrator used with Docker, automating many of the tasks involved in container management. With that in mind, all elements of the Kubernetes control plane must be secure. Here are some key areas you should be paying attention to.
First and foremost, it’s important to ensure secure access to the Kubernetes API. At a bare minimum, organisations should:
- Prevent anonymous logins.
- Perform authentication using a certification authority.
- Refrain from using ‘always allow’ as an authorisation mode for requests.
- Disable the ‘read-only’ port on Kubelet.
Kubernetes role-based access controls (RBAC) enable organisations to define the precise level of access and authorisation given to Kubernetes subjects, whether they’re human users, software, Kubelets, etc.
Organisations should ensure they’re taking full advantage of RBAC. This mode can be enforced through a flag option in the Kubernetes API configuration.
Kubernetes Users and Service Accounts must be defined and dedicated for cluster management; it’s recommended for users that do not have exclusive privileges on the cluster to log, authenticate and authorise using an external directory such as an Active Directory (AD).
API and security logs
A good rule of thumb for Kubernetes security is to ‘log anything that can be logged’. This ensures full visibility over what changes are being made (and by whom) at different levels – pods, containers, the API, etc. Having a well-configured log manager in place makes it easy for your SOC to retrieve and analyse logs if anything goes wrong.
Kubernetes security: The pod level
A Kubernetes pod is a collection of one or more containers. Ensuring security at the pod level is crucial, due to the huge number of potential threats. Here are the key considerations for ensuring your pods remain secure.
Kubernetes admission controller
An admission controller is a piece of code that intercepts requests to the Kubernetes API after the request has been authorised and authenticated. It essentially acts as a security gatekeeper by changing the request object or denying the request altogether if it doesn’t meet security standards. For example, admission controllers are commonly used to automatically disallow a container from running as root.
Kubernetes security context
A ‘security context’ field is used to define access control policies and privileges in a pod or container. Common ways to do this include:
- Defining a container to run as either privileged or unprivileged.
- Using SELinux/AppArmor to restrict access to objects and isolate applications from each other.
- Setting the filesystem of a container to read-only mode.
Pod security policies
The purpose of pod security policies (PSPs) is to ensure that pods only run if they meet a set of baseline security requirements. It’s worth noting that PSPs differ from security context, which only applies when a pod is already running.
Best practice for setting out PSPs is to simply forbid everything that hasn’t been previously allowed – considering the FIFO methodology. Another top tip is to consider using RBAC to filter the users and groups that can run a pod.
Implementing PSPs can get very complex. That’s why they’re currently being depreciated by Kubernetes. A simplified successor to PSPs, PodSecurity Admission, is poised to replace them.
NetworkPolicies enable users to specify how a pod is allowed to communicate with various network entities. Broadly speaking, they’re comparable with classic network firewalling (like iptables).
NetworkPolicies use a combination of the following identifiers: other pods, namespaces, and CIDR IP blocks. Abstracting concepts such as IP addresses or physical nodes won’t work because Kubernetes can change them dynamically.
Kubernetes resource allocation management
When you create a pod, make sure you specify how much CPU, RAM or ephemeral local storage it’ll need. This will help to prevent your resources from being hijacked by malicious actors and used for activities like illicit crypto mining.
Setting ‘requests’ and ‘limits’ is crucial here – think of these as a soft stop and a hard stop respectively. In a nutshell, if the node where a pod is running has enough resources available, it can use more resources than your request specifies. However, a container is never allowed to use more than the resource limit you’ve set for it.
A continuous approach to security
As you might imagine, the considerations set out in this article are only a skeleton and can be developed much further. Other areas you might want to address include:
- Implementing a robust DevSecOps strategy.
- Hardening your entire system – containers, Kubernetes clusters, other pipeline components, etc.
- Checking the compliance of your systems according to your organisation’s security policies.
- Implementing a threat detection and incident response strategy.
The bottom line? Like other software structures, containers aren’t secure by design. It’s up to security teams, developers and administrators at all levels to ensure an adequate security baseline is achieved.
More on Cybersecurity
Cyber Threat Intelligence Part 2 : How to support SOC’s Threat Hunting & Detection Engineering efforts
In the first part of this CTI focused blog posts series, we introduced the Intelligence Production Cycle and proposed a functional & technical architecture for a Cyber Threat Intelligence Platform integrated into and supporting both SOC and Incident Response (IR) operations.Read more
Remote working is not a new area for IT and cybersecurity experts, however in the last few years it has now been pushed to the forefront and become a hot topic that organisations globally must consider. From where we are currently sat, this change looks like it may be the new normal, and it is[...]Read more