From b78e4a6f63ce32fe796fcd0da88e15a78db8a71b Mon Sep 17 00:00:00 2001 From: otkd <7527203+otkd@users.noreply.github.com> Date: Fri, 2 Feb 2024 07:38:49 -0500 Subject: [PATCH] feat(Docker): add Secrets, Compose v2, Supply Chain Security, Podman (#1301) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(Docker): compose v2 & networking update - Updates Docker Compose references to use v2 `docker compose` command - Change ICC recommendation to use network policies instead of disabling Signed-off-by: otkd <7527203+otkd@users.noreply.github.com> * feat(Docker): add Docker Secrets rule - Following existing syntax adds Rule #13 covering Docker Secrets Signed-off-by: otkd <7527203+otkd@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Shlomo Zalman Heigh * feat(Docker): add Supply Chain Security & Podman - Merges the linting and container scanning section into a single rule - Fixes issue in proposed solution in Rule 10 doesn’t actually help implement the suggestion - Expand rootless mode - Add high level practices covering Docker supply chain security - Add Podman as an alternative to Docker for secure defaults Signed-off-by: otkd <7527203+otkd@users.noreply.github.com> --------- Signed-off-by: otkd <7527203+otkd@users.noreply.github.com> Co-authored-by: Shlomo Zalman Heigh --- cheatsheets/Docker_Security_Cheat_Sheet.md | 155 ++++++++++++++------- 1 file changed, 101 insertions(+), 54 deletions(-) diff --git a/cheatsheets/Docker_Security_Cheat_Sheet.md b/cheatsheets/Docker_Security_Cheat_Sheet.md index 8ad8ffc9c7..ca8911484d 100644 --- a/cheatsheets/Docker_Security_Cheat_Sheet.md +++ b/cheatsheets/Docker_Security_Cheat_Sheet.md @@ -2,17 +2,17 @@ ## Introduction -Docker is the most popular containerization technology. Upon proper use, it can increase the level of security (in comparison to running applications directly on the host). On the other hand, some misconfigurations can lead to downgrade the level of security or even introduce new vulnerabilities. +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 an easy to use list of common security mistakes and good practices that will help you secure your Docker containers. +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 prevent from known, container escapes vulnerabilities, which typically end in escalating to root/administrator privileges, patching Docker Engine and Docker Machine is crucial. +To protect against known container escape vulnerabilities like [Leaky Vessels](https://snyk.io/blog/cve-2024-21626-runc-process-cwd-container-breakout/), 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. -In addition, containers (unlike in virtual machines) share the kernel with the host, therefore kernel exploits executed inside the container will directly hit host kernel. For example, kernel privilege escalation exploit ([like Dirty COW](https://github.com/scumjr/dirtycow-vdso)) executed inside a well-insulated container will result in root access in a host. +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](https://github.com/scumjr/dirtycow-vdso) 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) @@ -21,11 +21,11 @@ Docker socket */var/run/docker.sock* is the UNIX socket that Docker is listening **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 un-encrypted 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](https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-socket-option). -**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. Remember that mounting the socket read-only is not a solution but only makes it harder to exploit. Equivalent in the docker-compose file is something like this: +**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. Remember that mounting the socket read-only is not a solution but only makes it harder to exploit. Equivalent in the docker compose file is something like this: ```yaml -volumes: -- "/var/run/docker.sock:/var/run/docker.sock" + volumes: + - "/var/run/docker.sock:/var/run/docker.sock" ``` ### RULE \#2 - Set a user @@ -49,9 +49,9 @@ Configuring the container to use an unprivileged user is the best way to prevent 3. Enable user namespace support (`--userns-remap=default`) in [Docker daemon](https://docs.docker.com/engine/security/userns-remap/#enable-userns-remap-on-the-daemon) -More information about this topic can be found at [Docker official documentation](https://docs.docker.com/engine/security/userns-remap/) +More information about this topic can be found at [Docker official documentation](https://docs.docker.com/engine/security/userns-remap/). For additional security, you can also run in rootless mode, which is discussed in [Rule \#12](#rule-12---run-docker-in-root-less-mode). -In kubernetes, this can be configured in [Security Context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) using `runAsNonRoot` field e.g.: +In Kubernetes, this can be configured in [Security Context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) using `runAsNonRoot` field e.g.: ```yaml kind: ... @@ -85,7 +85,7 @@ docker run --cap-drop all --cap-add CHOWN alpine **And remember: Do not run containers with the *--privileged* flag!!!** -In kubernetes this can be configured in [Security Context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) using `capabilities` field e.g.: +In Kubernetes this can be configured in [Security Context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) using `capabilities` field e.g.: ```yaml kind: ... @@ -109,11 +109,11 @@ spec: As a Kubernetes cluster administrator, you can configure it using [Pod Security Policies](https://kubernetes.io/docs/concepts/policy/pod-security-policy/). -### RULE \#4 - Add –no-new-privileges flag +### RULE \#4 - Prevent in-container privilege escalation -Always run your docker images with `--security-opt=no-new-privileges` in order to prevent escalate privileges using `setuid` or `setgid` binaries. +Always run your docker images with `--security-opt=no-new-privileges` in order to prevent privilege escalation. This will prevent the container from gaining new privileges via `setuid` or `setgid` binaries. -In kubernetes, this can be configured in [Security Context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) using `allowPrivilegeEscalation` field e.g.: +In Kubernetes, this can be configured in [Security Context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) using `allowPrivilegeEscalation` field e.g.: ```yaml kind: ... @@ -133,14 +133,13 @@ spec: As a Kubernetes cluster administrator, you can refer to Kubernetes documentation to configure it using [Pod Security Policies](https://kubernetes.io/docs/concepts/policy/pod-security-policy/). -### RULE \#5 - Disable inter-container communication (--icc=false) +### RULE \#5 - Be mindful of Inter-Container Connectivity -By default inter-container communication (icc) is enabled - it means that all containers can talk with each other (using [`docker0` bridged network](https://docs.docker.com/v17.09/engine/userguide/networking/default_network/container-communication/#communication-between-containers)). -This can be disabled by running docker daemon with `--icc=false` flag. -If icc is disabled (icc=false) it is required to tell which containers can communicate using --link=CONTAINER_NAME_or_ID:ALIAS option. -See more in [Docker documentation - container communication](https://docs.docker.com/v17.09/engine/userguide/networking/default_network/container-communication/#communication-between-containers) +Inter-Container Connectivity (icc) is enabled by default, allowing all containers to communicate with each other through the [`docker0` bridged network](https://docs.docker.com/network/drivers/bridge/). Instead of using the --icc=false flag with the Docker daemon, which completely disables inter-container communication, consider defining specific network configurations. This can be achieved by creating custom Docker networks and specifying which containers should be attached to them. This method provides more granular control over container communication. -In Kubernetes [Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) can be used for it. +For detailed guidance on configuring Docker networks for container communication, refer to the [Docker Documentation](https://docs.docker.com/network/#communication-between-containers). + +In Kubernetes environments, [Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) can be used to define rules that regulate pod interactions within the cluster. These policies provide a robust framework to control how pods communicate with each other and with other network endpoints. Additionally, [Network Policy Editor](https://networkpolicy.io/) simplifies the creation and management of network policies, making it more accessible to define complex networking rules through a user-friendly interface. ### RULE \#6 - Use Linux Security Module (seccomp, AppArmor, or SELinux) @@ -156,8 +155,7 @@ The best way to avoid DoS attacks is by limiting resources. You can limit [memor [Check documentation for more details about ulimits](https://docs.docker.com/engine/reference/commandline/run/#set-ulimits-in-container---ulimit) -You can also do this inside Kubernetes: [Assign Memory Resources to Containers and Pods](https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/), [Assign CPU Resources to Containers and Pods](https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/) and [Assign Extended Resources to a Container -](https://kubernetes.io/docs/tasks/configure-pod-container/extended-resource/) +You can also do this for Kubernetes: [Assign Memory Resources to Containers and Pods](https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/), [Assign CPU Resources to Containers and Pods](https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/) and [Assign Extended Resources to a Container](https://kubernetes.io/docs/tasks/configure-pod-container/extended-resource/) ### RULE \#8 - Set filesystem and volumes to read-only @@ -173,7 +171,7 @@ If an application inside a container has to save something temporarily, combine docker run --read-only --tmpfs /tmp alpine sh -c 'echo "whatever" > /tmp/file' ``` -Equivalent in the docker-compose file will be: +The Docker Compose `compose.yml` equivalent would be: ```yaml version: "3" @@ -183,7 +181,7 @@ services: read_only: true ``` -Equivalent in kubernetes in [Security Context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) will be: +Equivalent in Kubernetes in [Security Context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) will be: ```yaml kind: ... @@ -214,17 +212,36 @@ Or by using `--mount` option: docker run --mount source=volume-name,destination=/path/in/container,readonly alpine ``` -### RULE \#9 - Use static analysis tools +### RULE \#9 - Integrate container scanning tools into your CI/CD pipeline + +[CI/CD pipelines](CI_CD_Security_Cheat_Sheet.md) 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](https://dev-sec.io/baselines/docker/) +- [Use the Docker command line](https://docs.docker.com/engine/reference/commandline/cli/) +- [Overview of Docker Compose v2 CLI](https://docs.docker.com/compose/reference/overview/) +- [Configuring Logging Drivers](https://docs.docker.com/config/containers/logging/configure/) +- [View logs for a container or service](https://docs.docker.com/config/containers/logging/) +- [Dockerfile Security Best Practices](https://cloudberry.engineering/article/dockerfile-security-best-practices/) -To detect containers with known vulnerabilities - scan images using static analysis tools. + Container scanning tools are espescially important as part of a succesful 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](https://github.com/coreos/clair) - [ThreatMapper](https://github.com/deepfence/ThreatMapper) - - [Trivy](https://github.com/knqyf263/trivy) + - [Trivy](https://github.com/aquasecurity/trivy) - Commercial - [Snyk](https://snyk.io/) **(open source and free option available)** - - [anchore](https://anchore.com/opensource/) **(open source and free option available)** + - [Anchore](https://github.com/anchore/grype/) **(open source and free option available)** - [Docker Scout](https://www.docker.com/products/docker-scout/) **(open source and free option available)** - [JFrog XRay](https://jfrog.com/xray/) - [Qualys](https://www.qualys.com/apps/container-security/) @@ -246,47 +263,77 @@ To detect misconfigurations in Docker: - [dev-sec.io](https://dev-sec.io/baselines/docker/) - [Docker Bench for Security](https://github.com/docker/docker-bench-security) -### RULE \#10 - Set the logging level to at least INFO - -By default, the Docker daemon is configured to have a base logging level of 'info', and if this is not the case: set the Docker daemon log level to 'info'. Rationale: Setting up an appropriate log level, configures the Docker daemon to log events that you would want to review later. A base log level of 'info' and above would capture all logs except the debug logs. Until and unless required, you should not run docker daemon at the 'debug' log level. +### RULE \#10 - Keep the Docker daemon logging level at `info` -To configure the log level in docker-compose: +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 -docker-compose --log-level info up +ps aux | grep '[d]ockerd.*--log-level' | awk '{for(i=1;i<=NF;i++) if ($i ~ /--log-level/) print $i}' ``` -### Rule \#11 - Lint the Dockerfile at build time +Setting an appropriate log level, configures the Docker daemon to log events that you would want to review later. A base log level of 'info' and above would capture all logs except the debug logs. Until and unless required, you should not run docker daemon at the 'debug' log level. -Many issues can be prevented by following some best practices when writing the Dockerfile. Adding a security linter as a step in the build pipeline can go a long way in avoiding further headaches. Some issues that are worth checking are: +### Rule \#11 - Run Docker in rootless mode -- 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 +Rootless mode ensures that the Docker daemon and containers are running as an unprivileged user, which means that even if an attacker breaks out of the container, they will not have root privileges on the host, which in turn substantially limits the attack surface. This is different to [userns-remap](#rule-2---set-a-user) mode, where the daemon still operates with root privileges. -References: +Evaluate the [specific requirements](Attack_Surface_Analysis_Cheat_Sheet.md) and [security posture](Threat_Modeling_Cheat_Sheet.md) of your environment to determine if rootless mode is the best choice for you. For environments where security is a paramount concern and the [limitations of rootless mode](https://docs.docker.com/engine/security/rootless/#known-limitations) do not interfere with operational requirements, it is a strongly recommended configuration. Alternatively consider using [Podman](#podman-as-an-alternative-to-docker) as an alternative to Docker. -- [Docker Baselines on DevSec](https://dev-sec.io/baselines/docker/) -- [Use the Docker command line](https://docs.docker.com/engine/reference/commandline/cli/) -- [Overview of docker-compose CLI](https://docs.docker.com/compose/reference/overview/) -- [Configuring Logging Drivers](https://docs.docker.com/config/containers/logging/configure/) -- [View logs for a container or service](https://docs.docker.com/config/containers/logging/) -- [Dockerfile Security Best Practices](https://cloudberry.engineering/article/dockerfile-security-best-practices/) +> 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](https://docs.docker.com/engine/security/rootless/#prerequisites) are met. -### Rule \#12 - Run Docker in root-less mode +Read more about rootless mode and its limitations, installation and usage instructions on [Docker documentation](https://docs.docker.com/engine/security/rootless/) page. -Rootless mode ensures that the Docker daemon and containers are running as an unprivileged user, which means that even if an attacker breaks out of the container, they will not have root privileges on the host, which in turn substantially limits the attack surface. +### RULE \#12 - Utilize Docker Secrets for Sensitive Data Management -Rootless mode graduated from experimental in Docker Engine v20.10 and should be considered for added security, provided the [known limitations](https://docs.docker.com/engine/security/rootless/#known-limitations) are not an impediment. +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. -> 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](https://docs.docker.com/engine/security/rootless/#prerequisites) are met. -> Rootless mode was introduced in Docker Engine v19.03 as an experimental feature. Rootless mode graduated from experimental in Docker Engine v20.10. +```bash +docker secret create my_secret /path/to/super-secret-data.txt +docker service create --name web --secret my_secret nginx:latest +``` -Read more about rootless mode and its limitations, installation and usage instructions on [Docker documentation](https://docs.docker.com/engine/security/rootless/) page. +Or for Docker Compose: + +```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](Secrets_Management_Cheat_Sheet.md) for more information. + +### RULE \#13 - Enhance Supply Chain Security + +Building on the principles in [Rule \#9](#rule-9---integrate-container-scanning-tools-into-your-cicd-pipeline), 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](https://slsa.dev/spec/v1.0/provenance): Document the origin and history of container images to ensure traceability and integrity. +- [SBOM Generation](https://cyclonedx.org/guides/CycloneDX%20One%20Pager.pdf): Create a Software Bill of Materials (SBOM) for each image, detailing all components, libraries, and dependencies for transparency and vulnerability management. +- [Image Signing](https://github.com/notaryproject/notary): Digitally sign images to verify their integrity and authenticity, establishing trust in their security. +- [Trusted Registry](https://snyk.io/learn/container-security/container-registry-security/): Store the documented, signed images with their SBOMs in a secure registry that enforces strict [access controls](Access_Control_Cheat_Sheet.md) and supports metadata management. +- [Secure Deployment](https://www.openpolicyagent.org/docs/latest/#overview): 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](https://podman.io/) is an OCI-compliant, open-source container management tool developed by [Red Hat](https://www.redhat.com/en) 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. -## Related Projects +## References and Further Reading [OWASP Docker Top 10](https://github.com/OWASP/Docker-Security) +[Docker Security Best Practices](https://docs.docker.com/develop/security-best-practices/) +[Docker Engine Security](https://docs.docker.com/engine/security/) +[Kubernetes Security Cheat Sheet](Kubernetes_Security_Cheat_Sheet.md) +[SLSA - Supply Chain Levels for Software Artifacts](https://slsa.dev/) +[Sigstore](https://sigstore.dev/) +[Docker Build Attestation](https://docs.docker.com/build/attestations/) +[Docker Content Trust](https://docs.docker.com/engine/security/trust/)