Developers are smitten with containers. It’s no mystery why — they’re perfect partners for agile development and fast-paced DevOps environments. Containers start up in seconds and use a fraction of the resources of traditional VMs, making them ideal for microservices architectures and scalable apps. Convenience is a big part of the allure too: third party images make adding functionality as easy and quick as installing a new app on your smartphone. For developers and ops teams, containers such as Docker, are a match made in heaven.
But security pros are a bit more skeptical. Containers create new and unique vulnerabilities that need appropriate coverage. Much has been written about how to secure containers and I’m not writing to recap what Google can give you (see “Assessing the Current State of Container Security” and “5 Keys to Conquering Container Security” for starters). I’m writing to remind you that, like security in general, the biggest threat to container security is simple human fallibility and hubris.
Let’s start with some basics: Containers have a different attack surface than VMs. Here’s why: VMs offer dedicated (virtual) hardware that’s shared only by the applications running on that hardware. Containerized applications do not have this dedicated hardware layer. They run on the container OS, which in turn runs directly on the host OS and host hardware. Consequently, containers share hardware and (some) host OS resources with every other service running on that hardware. While this key difference in the technology stack is responsible for many desirable container characteristics (faster boot, more efficient use of resources), it also increases the attack surface for lateral movement through the host OS.
I’m also not writing this blog to rehash the container vs. VM security conversation (“Linux Containers vs. VMs: A Security Comparison” is a great overview). I’m writing to show you how human errors, shortcuts, and inattention can be particularly devastating when using containers. Here’s an (incomplete) list of common, if ill-advised, practices that can spoil our romance with containers:
- Using container images from untrusted sources — using containerized code from third parties can be a huge timesaver, but malicious malware can join the ride and infect other apps and services on the host hardware.
- Running containers as root — not surprisingly, developers hate troubleshooting privilege-related issues. But root on the container can equal root on the host, and that spells trouble well beyond the container.
- Using a “fully loaded” host OS distro in the container — it’s easier to include the kitchen sink in every container (and many 3rd-party containers do just that), but unused utilities and services can have vulnerabilities that make them an inviting target for attackers.
- Failing to protect each container — especially for containers that are short-lived or single-service, not including embedded security might seem reasonable to a time-pressed developer. This shortcut can spell security disaster.
- Accessing data sources through APIs that don’t authenticate or authorize connections — simplifying data access by skimping on access control simplifies life for developers but can expose sensitive records to devastating breaches.
- Failing to harden hosts — developing and maintaining policies for control groups and namespaces is complex. It’s even more complex when hardware is shared between containers. But you may regret taking the easy way out.
These are not intractable problems. Any skilled, well-staffed, and empowered security organization CAN develop a security regime that effectively addresses ALL attack surfaces, including those associated with containers.
In the real world, however, it pays to be paranoid. Assume developers will launch containers from untrusted sources. Expect configuration mistakes to be made. Understand that time pressures will lead to shortcuts. Trust, but verify. (Sorry, I got a little carried away. There’s really no “trusting” allowed).
So how can all of these hidden dangers be managed? How can anyone possibly anticipate all the security missteps that could open the door to disaster? At last year’s Black Hat, “behavior baselining” was one of the hottest topics on the floor and in the briefing rooms. It’s the best — and perhaps only — way to protect against the inevitable mistakes, misconfigurations, and human follies that afflict every IT shop, no matter how well run or expertly staffed.
Lacework provides a cloud workload security platform, called “Polygraph,” that is fully container-aware. Polygraph baselines container behaviors, (along with apps, processes, workloads, machines and users), tracks and monitors container provenance, ensures every container is automatically protected, and even optionally runs within a container itself.
Want to hear more? Stay tuned. My colleagues are going to dive into the specifics of how Polygraph protects containers in another post.