Skip to content
Sedat Özdemir
Writing

container-security

Armored Vehicle or Glass Jar? The Illusion of Container Isolation

Think your containers are bulletproof? Think again. Let’s dive into why shared kernels and privileged flags are a Red Teamer’s dream and how you can actually lock things down.

Sedat Özdemir
· 4 dk read

It’s 03:14 AM. A weird syscall anomaly pops up in the logs on my screen. A Kubernetes pod in the testCompany infrastructure was trying to access /proc/kcore—something it has absolutely no business doing. I put my coffee mug down and leaned into the terminal. Someone was trying to use the sweet flexibility of our microservices architecture as a stepping stone to breach the host machine. This was one of those critical moments where we realize container security is about much more than just running an 'image scan'.

Most people think containers are magic boxes that completely isolate everything inside from the outside world. But here’s the reality, buddy: Containers don't have their own kernel like Virtual Machines (VMs) do; they all share the same host kernel. This means if you don't close the door properly, a 'root' user inside the container can eventually become the master of your host system too.

The Infamous 'Privileged' Mode: Shooting Yourself in the Foot

Look, you know what the most common mistake I see in the field is? Setting privileged: true for a pod or container just to make the developer's life easier. That is exactly like saying, 'Here you go, brother, here are the keys to the system, do whatever you want.'

As a Red Teamer, the first place I look is the /dev folder. If I see the host machine's disks when I run ls /dev inside a container, the game is already over.

Let’s look at a defanged breakout example (Seriously, don't try this in production!):

# Malicious container start scenario (Representational)
# docker run --privileged --net=host -it alpine sh

# Attempting to access the host disk from inside the container
mkdir /mnt/host_root
mount /dev/sda1 /mnt/host_root

# Now we've reached the host system's /etc/shadow file!
cat /mnt/host_root/etc/shadow

The deal here is simple: if the user inside the container is root and has dangerous capabilities like CAP_SYS_ADMIN, isolation turns into a house of cards instantly.

The Docker Socket Disaster

Another 'classic' mistake is mounting the docker.sock file inside a container. This is usually done for monitoring tools or CI/CD pipelines. But the moment an attacker reaches that socket, they can create a new container via the Docker API and execute code on the host.

A defanged payload logic looks like this:

# If Docker socket access exists
curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" \
  -d '{"Image": "alpine", "Cmd": ["cat", "/etc/hostname"], "HostConfig": {"Binds": ["/:/host"]}}' \
  -X POST http://localhost/v1.24/containers/create

The Binds: ["/:/host"] part explains it all. Bind the host's root directory into the new container and jump in. Game over.

How Do We Build the Defensive Line?

Now let’s focus a bit on the 'how do we protect ourselves?' part. Here are a few golden rules we implement at testCompany to prevent these kinds of crises.

1. Rootless Containers

If you aren't running a container as the root user, the attacker's room for maneuver drops by about 90%.

Related posts