Docker Security
Docker Security
Docker Security
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.
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.
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.
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.
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:
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
2. During build time. Simple add user in Dockerfile and use it. For example:
FROM alpine
RUN groupadd -r myuser && useradd -r -g myuser myuser
<HERE DO WHAT YOU HAVE TO DO AS A ROOT USER LIKE INSTALLING PACKAGES ETC.>
USER myuser
More information about this topic can be found at Docker official documentation
(https://docs.docker.com/engine/security/userns-remap/)
kind: ...
apiVersion: ...
metadata:
name: ...
spec:
...
containers:
- name: ...
image: ....
securityContext:
...
runAsNonRoot: true
...
As a Kubernetes cluster administrator, you can configure it using Pod Security Policies
(https://kubernetes.io/docs/concepts/policy/pod-security-policy/).
The most secure setup is to drop all capabilities --cap-drop all and then add only required ones. For example:
kind: ...
apiVersion: ...
metadata:
name: ...
spec:
...
containers:
- name: ...
image: ....
securityContext:
...
capabilities:
drop:
- all
add:
- CHOWN
...
As a Kubernetes cluster administrator, you can configure it using Pod Security Policies
(https://kubernetes.io/docs/concepts/policy/pod-security-policy/).
kind: ...
apiVersion: ...
metadata:
name: ...
spec:
...
containers:
- name: ...
image: ....
securityContext:
...
allowPrivilegeEscalation: false
...
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/).
Instructions how to do this inside Kubernetes can be found at Security Context documentation
(https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) and in Kubernetes API documentation
(https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#securitycontext-v1-core)
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/)
If an application inside a container has to save something temporarily, combine --read-only flag with --tmpfs like
this:
docker run --read-only --tmpfs /tmp alpine sh -c 'echo "whatever" > /tmp/file'
version: "3"
services:
alpine:
image: alpine
read_only: true
Equivalent in kubernetes in Security Context (https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
will be:
kind: ...
apiVersion: ...
metadata:
name: ...
spec:
...
containers:
- name: ...
image: ....
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:
Free
Clair (https://github.com/coreos/clair)
ThreatMapper (https://github.com/deepfence/ThreatMapper)
Trivy (https://github.com/knqyf263/trivy)
Commercial
Snyk (https://snyk.io/) (open source and free option available)
anchore (https://anchore.com/opensource/) (open source and free option available)
JFrog XRay (https://jfrog.com/xray/)
Qualys (https://www.qualys.com/apps/container-security/)
kubeaudit (https://github.com/Shopify/kubeaudit)
kubesec.io (https://kubesec.io/)
kube-bench (https://github.com/aquasecurity/kube-bench)
inspec.io (https://www.inspec.io/docs/reference/resources/docker/)
dev-sec.io (https://dev-sec.io/baselines/docker/)
Docker Bench for Security (https://github.com/docker/docker-bench-security)
References:
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: