Ekaterina Gainullina, Security Vision
Introduction
Docker containers have long become an integral part of modern IT infrastructures due to their lightness and flexibility. However, despite all their advantages, they also have serious security drawbacks. One such drawback is the lack of reliable isolation between host and container. Security Vision, understanding the critical importance of protecting container environments, implements stringent security measures to minimise risks. Comprehensive measures allow Security Vision to effectively protect container environments, ensuring a high level of security for its customers and minimising potential risks.
Imagine a container with root access. It's like having a door with a lock, but the key to it matches all the locks in the house. An attacker with access to such a container could easily get to the host system's resources. Using privileged containers gives them full access to the system, allowing them to bypass many security mechanisms. This opens up huge opportunities for attackers, allowing them to perform actions that previously seemed impossible.
Exploiting Docker Socket to Increase Privilege: Detailed Overview
An attacker accesses the Docker Socket (/var/run/docker.sock). This socket is the interface to manage the Docker API, which allows them to perform various operations on Docker containers and images. It's like giving them a remote control with which they can start and stop containers, change their configurations, and even run containers with root access. This access allows attackers to take control of the entire system, including the ability to execute arbitrary code on the host. By exploiting the ability to mount the host's file system into a container using the -v /:/host option, an attacker can access the host's files and directories directly from the container. This is an important step to explore and manipulate files that may contain sensitive information or data, including /etc/shadow for privilege escalation capabilities.
Next, various options and flags are used to remove the restrictions placed on containers:
- --privileged: This flag removes all isolation measures and restrictions, giving the container full access to the host system. This is a very dangerous practice as the container loses all the isolation and security benefits provided by Docker.
- --cap-add=ALL: Adding all Linux capabilities to the container, which can allow an attacker to perform privileged operations.
- --security-opt apparmor=unconfined and --security-opt seccomp=unconfined: Disabling the AppArmor and Seccomp security profiles for the container, which reduces the level of protection provided by Docker. Often, attackers attempt to access the host file system by mounting disc devices directly into the container. For example, using the option combination
--device=/dev/sda1 --cap-add=SYS_ADMIN --security-opt apparmor=unconfined, a specific disk device can be mounted into the container. The attacker can then use themount /dev/sda1 /mntcommand in the container to access the contents of the host disc via the/mntmount point .
Often attackers find writable directories on the host that can be mounted in the container. For example, with -v /tmp:/host, the host's /tmp directory can be mounted into a container. An attacker can then create an executable file with a SUID in the mounted directory, allowing them to execute it with elevated privileges on the host. If root privileges are obtained in the container, the attacker can modify host system configuration files, such as /etc, which can result in a severe privilege escalation on the host. For example, modifying /etc/shadow can open access to user accounts on the host system. To escape from a container, attackers use the --privileged flag or adding appropriate capabilities while disabling other defences. This allows an attacker to escape the isolation of the container and gain full access to the host system.
OWASP's Docker Security Quick Start Guide
Keep your host and Docker up to date
To protect against known vulnerabilities such as Leaky Vessels, which typically allow an attacker to gain root access to a host, it is critical to regularly update both the host and Docker. This includes regularly updating the host kernel and the Docker engine.
Do not expose the Docker daemon socket
The Docker socket /var/run/docker.sock is the UNIX socket that Docker subscribes to and through which the Docker API is accessed. The owner of this socket is root. Granting access to it is equivalent to granting unrestricted root access to your host. If you run your Docker image with -v /var/run/docker.sock:/var/run/docker.sock or similar, you should change this. Remember that mounting a read-only socket is not a solution, it just makes it harder to exploit. An equivalent declaration in a docker-compose file might look like this:
volumes:
- ‘/var/run/docker.sock:/var/run/docker.sock’.
Set the user
Configuring a container to be used by an unprivileged user is the best way to prevent privilege escalation attacks. In Kubernetes, this can be configured in a security context by using the runAsUser field with a user ID such as:
apiVersion: v1
kind: Pod
metadata:
name: example
spec:
containers:
- name: example
image: gcr.io/google-samples/node-hello:1.0
securityContext:
runAsUser: 4000 # <-- This is the user id of the submitted user
As a Kubernetes cluster administrator, you can set up an enhanced configuration using the Restricted layer with the built-in Pod security admission controller, and if more customisation is required, consider using Admission Webhooks or alternative third-party solutions.
Limit capabilities
Limit the privileges of the container by providing only the capabilities you need.
Do not run containers with the --privileged flag!!! In Kubernetes, this can be configured in a security context using a capability field such as:
apiVersion: v1
kind: Pod
metadata:
name: example
spec:
containers:
- name: example
image: gcr.io/google-samples/node-hello:1.0
securityContext:
capabilities:
drop:
- ALL
add: [‘CHOWN’].
Prevent privilege escalation within the container
Run your Docker images with the --security-opt=no-new-privileges flag to prevent privilege escalation.
In Kubernetes, this can be configured in a security context using the ‘allow privilege escalation’ field, for example:
apiVersion: v1
kind: Pod
metadata:
name: example
spec:
containers:
- name: example
image: gcr.io/google-samples/node-hello:1.0
securityContext:
allowPrivilegeEscalation: false
Limit resources (memory, CPU, file descriptors, processes, restarts)
The best way to avoid DoS attacks is to limit resources.
Set the file system and volumes to read-only mode
Run containers with the file system in read-only mode.
Integrate container scanning tools into your CI/CD Pipeline
CI/CD Pipelines are an important part of the software development lifecycle and should include various security checks such as container scanning.
Conclusion
Controlling access to Docker Socket is critical as it can become a tool in the hands of attackers. Security Vision strictly limits access to it, preventing unauthorised management of containers and hosts. Running containers as unprivileged users helps minimise the risk of privilege escalation. Restrictions on container resources such as memory and CPU are imposed to prevent DoS attacks. Containers are started with the file system in read-only mode, which limits the ability of attackers to modify data. Security Vision integrates container scanning tools into its CI/CD Pipelines, ensuring security at all stages of development. These measures allow Security Vision to effectively protect container environments, minimising risk and ensuring a high level of security for its customers.