Skip to content
Sedat Özdemir
Writing

container-security

Docker's 'Privileged' Trap: Trojan Horses Inside Containers

Think that --privileged flag is a lifesaver? Think again. Here is how container misconfigurations turn into open doors for attackers, based on my early career blunders and Red Team field experience.

Sedat Özdemir
· 4 dk read

Years ago, back when I was first getting my feet wet with container technologies, I was trying to build a microservices architecture at 'testCompany'. There was this one image that just wouldn't start; it kept throwing 'permission denied' errors. Back then, I was definitely in the 'the fastest solution is the best solution' mindset. I saw an answer on Stack Overflow: --privileged. I added the command, and suddenly everything started working. Great, right? Well, it turns out that day I had opened the gates to the heart of the system wide open. I only realized the gravity of the situation a week later during an internal penetration test when a teammate grabbed a root shell on the host machine with a single command. Ever since that day, I get the chills whenever someone mentions container security.

Today, I’m going to talk to you about those rookie mistakes I made and how we, in our Red Team operations, slip through containers like a hot knife through butter. Grab your coffee, because this isn't just about running 'docker build'.

Image Bloat and Hidden Dangers

Most of us choose the path of least resistance when writing a Dockerfile: FROM ubuntu:latest. However, this brings along a massive attack surface. Every single library or tool you don't need (curl, netcat, python, compilers) is a 'post-exploitation' tool for an attacker. If your image contains gcc or curl, you're essentially making it easier for an attacker who breaches the system to download and compile malware.

Let’s look at this example:

# ZAYIF ÖRNEK
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y python3 curl netcat
COPY ./app /app
WORKDIR /app
# Uygulamayı root kullanıcısı olarak çalıştırıyor
CMD ["python3", "app.py"]

The problem here isn't just the bloat; it's that the application runs with root privileges by default. If there’s a Remote Code Execution (RCE) vulnerability in app.py, the attacker immediately becomes root inside the container. Jumping from there to the host is child's play.

Capabilities: Silent But Deep

Containers share the capabilities of the Linux kernel. Docker restricts some 'capabilities' by default, but sometimes (like my old mistake) we open everything up. Using the --privileged flag means the container can access all hardware and kernel features on the host machine. This completely eliminates isolation.

Let’s look at it from an attacker's perspective. If a container has CAP_SYS_ADMIN privileges, the attacker can mount the host's disks.

# Saldırganın konteyner içinde çalıştırabileceği bir 'escape' örneği (defanged)
# Host'un ana diskini bularak kendi içine mount etmeye çalışır
mount /dev/sda1 /mnt/host_root
# Artık host makinenin /etc/shadow dosyasına erişebilir!
cat /mnt/host_root/etc/shadow

Instead, you should apply the 'Least Privilege' principle. Give only the authority you need, nothing more.

docker run --clear-capabilities --add-capability CAP_NET_BIND_SERVICE example-image

Environment V...

Related posts