Container Security
“Let’s move to containers” promised engineering simplicity, security, and easy scaling … but there was a catch. 🙊
The simplicity and security gains were only true if containers were used as intended. Turns out it’s really an entirely new system that replaced the equally complex old system, but with different tradeoffs to consider as we built new systems. That’s not a bad thing and it isn’t as complicated or scary as it sounds.
🧭 Let’s navigate the intersection of application security and containerization and systems design together. 🧭
Where we’re headed
This is the system we’re going to look at fully assembled. Using the map below, let’s dig into how to threat model and talk about the security risks at each part. Then we’ll look at how it gets put together and think about the security of this system as a whole.
A meandering stroll through container security
Coming soon
- Host risks and shenanigans
- Runtime fun time
- Orchestrating chaos
- Where do images come from?
- … but what is in those images, though?
- Real world risks - or “not everything you read in an industry white paper is important” and other lessons learned the hard way
Hands-on examples
Setup instructions for all the hands-on examples below 👷🏻♀️
Enumeration
- Who am I? - Let’s get oriented and figure out what we have in our container.
- Our shared kernel - Containers are processes that share a kernel. What can we see?
- Are we capable? - What sort of capabilities do we have?
- Seccomp is your friend - Seccomp filters what a container can do. Let’s learn what’s been set for us.
- Are we in a microVM? - With microVM runtimes gaining popularity, how do you know if you’re in a container?
Escapes
- Persistent storage - Persisting through persistent storage
- Finding secrets in image layers - Finding secrets in a container image’s layers can be done at runtime if you have access to download it and a shell or access to the host’s socket or access to the registry.
-
Chrooooooooot -
chroot
right on out of a container’s filesystem. - Runtime groups - The default “docker” group is basically root.
- Shared runtime sockets - Let’s use a shared socket to create a new container
- Messing with the host’s memory - Let’s modify a process in memory to do fun things!
- Vulnerable apps in the wild - You’re typically not SSH’d into the container host, so … how does this still work in the wild?
- (coming soon) Do you really need a runtime?
This small collection of my favorite container escapes may grow over time too. 😈
This is part of a series put together from client-facing conversations, conference talks, workshops, and more over the past 10 years of asking folks to stop doing silly things in containers. Many slides were taken from my talk at BSides Boulder 2025 and the hands-on exercises from my workshop at AppSec Village @ DEF CON 33 .
👷🏻♀️ (this page is a work in progress, to be assembled over summer 2025 🏖️)