Docker Engine security
Page options
There are four major areas to consider when reviewing Docker security:
- The intrinsic security of the kernel and its support fornamespaces and cgroups
- The attack surface of the Docker daemon itself
- Loopholes in the container configuration profile, either by default,or when customized by users.
- The "hardening" security features of the kernel and how theyinteract with containers.
Kernel namespaces
Docker containers are very similar to LXC containers, and they havesimilar security features. When you start a container withdocker run
, behind the scenes Docker creates a set of namespaces and controlgroups for the container.
Namespaces provide the first and most straightforward form ofisolation. Processes running within a container cannot see, and evenless affect, processes running in another container, or in the hostsystem.
Each container also gets its own network stack, meaning that acontainer doesn't get privileged access to the sockets or interfacesof another container. Of course, if the host system is setupaccordingly, containers can interact with each other through theirrespective network interfaces — just like they can interact withexternal hosts. When you specify public ports for your containers or uselinksthen IP traffic is allowed between containers. They can ping each other,send/receive UDP packets, and establish TCP connections, but that can berestricted if necessary. From a network architecture point of view, allcontainers on a given Docker host are sitting on bridge interfaces. Thismeans that they are just like physical machines connected through acommon Ethernet switch; no more, no less.
How mature is the code providing kernel namespaces and privatenetworking? Kernel namespaces were introducedbetween kernel version2.6.15 and2.6.26.This means that since July 2008 (date of the 2.6.26 release), namespace code has been exercised and scrutinized on a largenumber of production systems. And there is more: the design andinspiration for the namespaces code are even older. Namespaces areactually an effort to reimplement the features ofOpenVZ in such a way that they could bemerged within the mainstream kernel. And OpenVZ was initially releasedin 2005, so both the design and the implementation are pretty mature.
Control groups
Control Groups are another key component of Linux containers. Theyimplement resource accounting and limiting. They provide manyuseful metrics, but they also help ensure that each container getsits fair share of memory, CPU, disk I/O; and, more importantly, that asingle container cannot bring the system down by exhausting one of thoseresources.
So while they do not play a role in preventing one container fromaccessing or affecting the data and processes of another container, theyare essential to fend off some denial-of-service attacks. They areparticularly important on multi-tenant platforms, like public andprivate PaaS, to guarantee a consistent uptime (and performance) evenwhen some applications start to misbehave.
Control Groups have been around for a while as well: the code wasstarted in 2006, and initially merged in kernel 2.6.24.
Docker daemon attack surface
Running containers (and applications) with Docker implies running theDocker daemon. This daemon requiresroot
privileges unless you opt-intoRootless mode, and you should therefore be aware ofsome important details.
First of all, only trusted users should be allowed to control yourDocker daemon. This is a direct consequence of some powerful Dockerfeatures. Specifically, Docker allows you to share a directory betweenthe Docker host and a guest container; and it allows you to do sowithout limiting the access rights of the container. This means that youcan start a container where the/host
directory is the/
directoryon your host; and the container can alter your host filesystemwithout any restriction. This is similar to how virtualization systemsallow filesystem resource sharing. Nothing prevents you from sharing yourroot filesystem (or even your root block device) with a virtual machine.
This has a strong security implication: for example, if you instrument Dockerfrom a web server to provision containers through an API, you should beeven more careful than usual with parameter checking, to make sure thata malicious user cannot pass crafted parameters causing Docker to createarbitrary containers.
For this reason, the REST API endpoint (used by the Docker CLI tocommunicate with the Docker daemon) changed in Docker 0.5.2, and nowuses a Unix socket instead of a TCP socket bound on 127.0.0.1 (thelatter being prone to cross-site request forgery attacks if you happen to runDocker directly on your local machine, outside of a VM). You can thenuse traditional Unix permission checks to limit access to the controlsocket.
You can also expose the REST API over HTTP if you explicitly decide to do so.However, if you do that, be aware of the above mentioned security implications.Note that even if you have a firewall to limit accesses to the REST APIendpoint from other hosts in the network, the endpoint can be still accessiblefrom containers, and it can easily result in the privilege escalation.Therefore it ismandatory to secure API endpoints withHTTPS and certificates.Exposing the daemon API over HTTP without TLS is not permitted,and such a configuration causes the daemon to fail early on startup, seeUnauthenticated TCP connections.It is also recommended to ensure that it is reachable only from a trustednetwork or VPN.
You can also useDOCKER_HOST=ssh://USER@HOST
orssh -L /path/to/docker.sock:/var/run/docker.sock
instead if you prefer SSH over TLS.
The daemon is also potentially vulnerable to other inputs, such as imageloading from either disk withdocker load
, or from the network withdocker pull
. As of Docker 1.3.2, images are now extracted in a chrootedsubprocess on Linux/Unix platforms, being the first-step in a wider efforttoward privilege separation. As of Docker 1.10.0, all images are stored andaccessed by the cryptographic checksums of their contents, limiting thepossibility of an attacker causing a collision with an existing image.
Finally, if you run Docker on a server, it is recommended to runexclusively Docker on the server, and move all other services withincontainers controlled by Docker. Of course, it is fine to keep yourfavorite admin tools (probably at least an SSH server), as well asexisting monitoring/supervision processes, such as NRPE and collectd.
Linux kernel capabilities
By default, Docker starts containers with a restricted set ofcapabilities. What does that mean?
Capabilities turn the binary "root/non-root" dichotomy into afine-grained access control system. Processes (like web servers) thatjust need to bind on a port below 1024 do not need to run as root: theycan just be granted thenet_bind_service
capability instead. And thereare many other capabilities, for almost all the specific areas where rootprivileges are usually needed. This means a lot for container security.
Typical servers run several processes asroot
, including the SSH daemon,cron
daemon, logging daemons, kernel modules, network configuration tools,and more. A container is different, because almost all of those tasks arehandled by the infrastructure around the container:
- SSH access are typically managed by a single server running onthe Docker host
cron
, when necessary, should run as a userprocess, dedicated and tailored for the app that needs itsscheduling service, rather than as a platform-wide facility- Log management is also typically handed to Docker, or tothird-party services like Loggly or Splunk
- Hardware management is irrelevant, meaning that you never need torun
udevd
or equivalent daemons withincontainers - Network management happens outside of the containers, enforcingseparation of concerns as much as possible, meaning that a containershould never need to perform
ifconfig
,route
, or ip commands (except when a containeris specifically engineered to behave like a router or firewall, ofcourse)
This means that in most cases, containers do not need "real" rootprivileges at all* And therefore, containers can run with a reducedcapability set; meaning that "root" within a container has much lessprivileges than the real "root". For instance, it is possible to:
- Deny all "mount" operations
- Deny access to raw sockets (to prevent packet spoofing)
- Deny access to some filesystem operations, like creating new devicenodes, changing the owner of files, or altering attributes (includingthe immutable flag)
- Deny module loading
This means that even if an intruder manages to escalate to root within acontainer, it is much harder to do serious damage, or to escalateto the host.
This doesn't affect regular web apps, but reduces the vectors of attack bymalicious users considerably. By default Dockerdrops all capabilities exceptthoseneeded,an allowlist instead of a denylist approach. You can see a full list ofavailable capabilities inLinuxmanpages.
One primary risk with running Docker containers is that the default setof capabilities and mounts given to a container may provide incompleteisolation, either independently, or when used in combination withkernel vulnerabilities.
Docker supports the addition and removal of capabilities, allowing useof a non-default profile. This may make Docker more secure throughcapability removal, or less secure through the addition of capabilities.The best practice for users would be to remove all capabilities exceptthose explicitly required for their processes.
Docker Content Trust signature verification
Docker Engine can be configured to only run signed images. The Docker ContentTrust signature verification feature is built directly into thedockerd
binary.
This is configured in the Dockerd configuration file.
To enable this feature, trustpinning can be configured indaemon.json
, wherebyonly repositories signed with a user-specified root key can be pulled and run.
This feature provides more insight to administrators than previously available withthe CLI for enforcing and performing image signature verification.
For more information on configuring Docker Content Trust Signature Verification, go toContent trust in Docker.
Other kernel security features
Capabilities are just one of the many security features provided bymodern Linux kernels. It is also possible to leverage existing,well-known systems like TOMOYO, AppArmor, SELinux, GRSEC, etc. withDocker.
While Docker currently only enables capabilities, it doesn't interferewith the other systems. This means that there are many different ways toharden a Docker host. Here are a few examples.
- You can run a kernel with GRSEC and PAX. This adds many safetychecks, both at compile-time and run-time; it also defeats manyexploits, thanks to techniques like address randomization. It doesn'trequire Docker-specific configuration, since those security featuresapply system-wide, independent of containers.
- If your distribution comes with security model templates forDocker containers, you can use them out of the box. For instance, weship a template that works with AppArmor and Red Hat comes with SELinuxpolicies for Docker. These templates provide an extra safety net (eventhough it overlaps greatly with capabilities).
- You can define your own policies using your favorite access controlmechanism.
Just as you can use third-party tools to augment Docker containers, includingspecial network topologies or shared filesystems, tools exist to harden Dockercontainers without the need to modify Docker itself.
As of Docker 1.10 User Namespaces are supported directly by the dockerdaemon. This feature allows for the root user in a container to be mappedto a non uid-0 user outside the container, which can help to mitigate therisks of container breakout. This facility is available but not enabledby default.
Refer to thedaemon commandin the command line reference for more information on this feature.Additional information on the implementation of User Namespaces in Dockercan be found inthis blog post.
Conclusions
Docker containers are, by default, quite secure; especially if yourun your processes as non-privileged users inside the container.
You can add an extra layer of safety by enabling AppArmor, SELinux,GRSEC, or another appropriate hardening system.
If you think of ways to make docker more secure, we welcome feature requests,pull requests, or comments on the Docker community forums.