OWASPCheat Sheet
CS-Docker_Security Docker Security Cheat Sheet
- Project
- OWASP Cheat Sheet Series
Introduction
Docker is the most popular containerization technology. When used correctly, it can enhance security compared to running applications directly on the host system. However, certain misconfigurations can reduce security levels or introduce new vulnerabilities.
The aim of this cheat sheet is to provide a straightforward list of common security errors and best practices to assist in securing your Docker containers.
Rules
RULE \#0 - Keep Host and Docker up to date
To protect against known container escape vulnerabilities like Leaky Vessels, which typically result in the attacker gaining root access to the host, it's vital to keep both the host and Docker up to date. This includes regularly updating the host kernel as well as the Docker Engine.
This is due to the fact that containers share the host's kernel. If the host's kernel is vulnerable, the containers are also vulnerable. For example, the kernel privilege escalation exploit, Dirty COW, executed inside a well-insulated container would still result in root access on a vulnerable host.
RULE \#1 - Do not expose the Docker daemon socket (even to the containers)
Docker socket _/var/run/docker.sock_ is the UNIX socket that Docker is listening to. This is the primary entry point for the Docker API. The owner of this socket is root. Giving someone access to it is equivalent to giving unrestricted root access to your host.
Do not enable _tcp_ Docker daemon socket. If you are running docker daemon with `-H tcp://0.0.0.0:XXX` or similar you are exposing unencrypted and unauthenticated direct access to the Docker daemon, if the host is internet connected this means the docker daemon on your computer can be used by anyone from the public internet.
If you really, really have to do this, you should secure it. Check how to do this following Docker official documentation.
Do not expose _/var/run/docker.sock_ to other containers. If you are running your docker image with `-v /var/run/docker.sock://var/run/docker.sock` or similar, you should change it. Mounting the socket read-only does not make the Docker API read-only: a process that can connect to the socket can still send requests that modify containers or the host. Docker grants access to all daemon commands by default; filesystem mount flags do not replace API authorization. Equivalent in the docker compose file is something like this:
```yaml
volumes:
• "/var/run/docker.sock:/var/run/docker.sock"
```
RULE \#2 - Set a user
Configuring the container to use an unprivileged user is the best way to prevent privilege escalation attacks. This can be accomplished in three different ways as follows:
1. During runtime using `-u` option of `docker run` command e.g.:
```bash
docker run -u 4000 alpine
```
2. During build time. Simply add user in Dockerfile and use it. For example:
```dockerfile
FROM alpine
RUN groupadd -r myuser && useradd -r -g myuser myuser
#
USER myuser
```
3. Enable user namespace support (`--userns-remap=default`) in Docker daemon
More information about this topic can be found at Docker official documentation. For additional security, you can also run in rootless mode, which is discussed in Rule \#11.
In Kubernetes, this can be configured in Security Context using the `runAsUser` field with the user ID e.g:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: example
spec:
containers:
• name: example
image: gcr.io/google-samples/node-hello:1.0
securityContext:
runAsUser: 4000 # `), maximum number of file descriptors (`--ulimit nofile=`) and maximum number of processes (`--ulimit nproc=`).
Check documentation for more details about ulimits
You can also do this for Kubernetes: Assign Memory Resources to Containers and Pods, Assign CPU Resources to Containers and Pods and Assign Extended Resources to a Container
RULE \#8 - Set filesystem and volumes to read-only
Run containers with a read-only filesystem using `--read-only` flag. For example:
```bash
docker run --read-only alpine sh -c 'echo "whatever" > /tmp'
```
If an application inside a container has to save something temporarily, combine `--read-only` flag with `--tmpfs` like this:
```bash
docker run --read-only --tmpfs /tmp alpine sh -c 'echo "whatever" > /tmp/file'
```
The Docker Compose `compose.yml` equivalent would be:
```yaml
version: "3"
services:
alpine:
image: alpine
read_only: true
```
Equivalent in Kubernetes in Security Context:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: example
spec:
containers:
• name: example
image: gcr.io/google-samples/node-hello:1.0
securityContext:
readOnlyRootFilesystem: true
```
In addition, if the volume is mounted only for reading mount them as a read-only
It can be done by appending `:ro` to the `-v` like this:
```bash
docker run -v volume-name:/path/in/container:ro alpine
```
Or by using `--mount` option:
```bash
docker run --mount source=volume-name,destination=/path/in/container,readonly alpine
```
RULE \#9 - Integrate container scanning tools into your CI/CD pipeline
CI/CD pipelines are a crucial part of the software development lifecycle and should include various security checks such as lint checks, static code analysis, and container scanning.
Many issues can be prevented by following some best practices when writing the Dockerfile. However, adding a security linter as a step in the build pipeline can go a long way in avoiding further headaches. Some issues that are commonly checked are:
• Ensure a `USER` directive is specified
• Ensure the base image version is pinned
• Ensure the OS packages versions are pinned
• Avoid the use of `ADD` in favor of `COPY`
• Avoid curl bashing in `RUN` directives
References:
• Docker Baselines on DevSec
• Use the Docker command line
• Overview of Docker Compose v2 CLI
• Configuring Logging Drivers
• View logs for a container or service
• Dockerfile Security Best Practices
Container scanning tools are especially important as part of a successful security strategy. They can detect known vulnerabilities, secrets and misconfigurations in container images and provide a report of the findings with recommendations on how to fix them. Some examples of popular container scanning tools are:
• Free
• Clair
• Grype
• Trivy
• Commercial
• Snyk (open source and free option available)
• Anchore (open source and free option available)
• Docker Scout (open source and free option available)
• JFrog XRay
• Qualys
To detect secrets in images:
• ggshield (open source and free option available)
• Gitleaks (open source)
• TruffleHog (open source)
To detect misconfigurations in Kubernetes:
• kubeaudit
• kubesec.io
• kube-bench
To detect misconfigurations in Docker:
• inspec.io
• dev-sec.io
• Docker Bench for Security
To detect misconfigurations in Docker Compose files before deployment:
• DockSec (with `--compose`)
• KICS
RULE \#10 - Keep the Docker daemon logging level at `info`
By default, the Docker daemon is configured to have a base logging level of `info`. This can be verified by checking the daemon configuration file `/etc/docker/daemon.json` for the`log-level` key. If the key is not present, the default logging level is `info`. Additionally, if the docker daemon is started with the `--log-level` option, the value of the `log-level` key in the configuration file will be overridden. To check if the Docker daemon is running with a different log level, you can use the following command:
```bash
ps aux | grep '[d]ockerd.*--log-level' | awk '{for(i=1;i Rootless mode allows running the Docker daemon and containers as a non-root user to mitigate potential vulnerabilities in the daemon and the container runtime.
> Rootless mode does not require root privileges even during the installation of the Docker daemon, as long as the prerequisites are met.
Read more about rootless mode and its limitations, installation and usage instructions on Docker documentation page.
RULE \#12 - Utilize Docker Secrets for Sensitive Data Management
Docker Secrets provide a secure way to store and manage sensitive data such as passwords, tokens, and SSH keys. Using Docker Secrets helps in avoiding the exposure of sensitive data in container images or in runtime commands.
```bash
docker secret create my_secret /path/to/super-secret-data.txt
docker service create --name web --secret my_secret nginx:latest
```
For local Docker Compose, file-backed secrets are bind mounts. Protect the source files on the host with appropriate access permissions and storage encryption; declaring a Compose secret does not encrypt these files. This differs from Swarm-managed secrets, which are distributed over mutual TLS and stored in an encrypted Raft log:
```yaml
version: "3.8"
secrets:
my_secret:
file: ./super-secret-data.txt
services:
web:
image: nginx:latest
secrets:
• my_secret
```
While Docker Secrets generally provide a secure way to manage sensitive data in Docker environments, this approach is not recommended for Kubernetes, where secrets are stored in plaintext by default. In Kubernetes, consider using additional security measures such as etcd encryption, or third-party tools. Refer to the Secrets Management Cheat Sheet and Kubernetes Security Cheat Sheet for more information.
RULE \#13 - Enhance Supply Chain Security
Building on the principles in Rule \#9, enhancing supply chain security involves implementing additional measures to secure the entire lifecycle of container images from creation to deployment. Some of the key practices include:
• Image Provenance: Document the origin and history of container images to ensure traceability and integrity.
• SBOM Generation: Create a Software Bill of Materials (SBOM) for each image, detailing all components, libraries, and dependencies for transparency and vulnerability management.
• Image Signing: Digitally sign images to verify their integrity and authenticity, establishing trust in their security.
• Trusted Registry: Store the documented, signed images with their SBOMs in a secure registry that enforces strict access controls and supports metadata management.
• Secure Deployment: Implement secure deployment polices, such as image validation, runtime security, and continuous monitoring, to ensure the security of the deployed images.
Podman as an alternative to Docker
Podman is an OCI-compliant, open-source container management tool developed by Red Hat that provides a Docker-compatible command-line interface and a desktop application for managing containers. It is designed to be a more secure and lightweight alternative to Docker, especially for environments where secure defaults are preferred. Some of the security benefits of Podman include:
1. Daemonless Architecture: Unlike Docker, which requires a central daemon (dockerd) to create, run, and manage containers, Podman directly employs the fork-exec model. When a user requests to start a container, Podman forks from the current process, then the child process execs into the container's runtime.
2. Rootless Containers: The fork-exec model facilitates Podman's ability to run containers without requiring root privileges. When a non-root user initiates a container start, Podman forks and execs under the user's permissions.
3. SELinux Integration: Podman is built to work with SELinux, which provides an additional layer of security by enforcing mandatory access controls on containers and their interactions with the host system.
References
Related
Referenced by OWASP · cheat sheet (1)
- CS-NodeJS_Docker Node.js Docker Cheat Sheet Cheat Sheet