notes 2026-09-20 · 3 min read

Linux Privilege Escalation and Container Escapes

Capabilities, systemd units, Unix and Docker sockets, namespaces and cgroups: where root splits into pieces and where isolation actually breaks.

Linux Privilege Escalation and Container Escapes

Root on Linux is not one privilege, and a container is not one boundary. Both are made of parts that can be held separately, which is what makes these paths work.

Linux Capabilities

A process can have a normal UID while carrying exactly the capability needed to cross the boundary you were relying on. Capabilities split root privilege into units such as CAP_SETUID, CAP_DAC_OVERRIDE, CAP_NET_ADMIN and CAP_SYS_ADMIN. File capabilities and ambient capabilities change what a binary inherits at execution. The bounding set limits the maximum available set. I use getcap, capsh and /proc to inspect effective, permitted, inheritable and bounding sets before testing the matching operation. CAP_SYS_ADMIN is extremely broad. Other capabilities become privilege escalation only when the binary exposes a useful primitive.

1
2
getcap -r / 2>/dev/null
capsh --print

systemd

A root-owned service file may still be vulnerable when ExecStart points to a script a regular user can modify. systemd units define executable, user, environment, working directory and dependencies. Drop-ins may override parts of configuration. Writable scripts, EnvironmentFile entries, paths and sudo permission to restart services form common privilege-escalation chains. I use systemctl cat, show and filesystem permissions to follow every path consumed by the unit. Hardening options such as NoNewPrivileges, ProtectSystem and capability restrictions reduce impact but do not fix a writable root-executed script.

1
2
systemctl cat backup.service
systemctl show backup.service -p User,ExecStart,EnvironmentFiles

Unix Sockets and Docker Socket

A socket file may look like another inode until you realize it is the entrance to a daemon running as root. Unix domain sockets use filesystem permissions and local credentials to control access to daemons. docker.sock, containerd sockets, libvirt and custom services may expose administrative APIs over local sockets. I list sockets, owners, groups and protocol before sending any request. curl –unix-socket is useful for local HTTP APIs. A user in the socket-authorized group inherits daemon power. Tightening file mode without reviewing group membership may leave the path open.

1
2
find /run /var/run -type s -ls 2>/dev/null | head -80
curl --unix-socket /var/run/docker.sock http://localhost/version

Namespaces, cgroups and Escapes

A container does not create a new kernel. It shares the host kernel and uses namespaces, cgroups and policy to reduce what a process can see and do. Namespaces isolate pid, mount, network, user and other resources. cgroups control grouping and resource usage. Capabilities and seccomp reduce powers and syscalls. Privileged mode, hostPID, hostNetwork, hostPath, devices and kernel vulnerabilities may cross these boundaries. I identify namespaces, mounts, capabilities, seccomp, AppArmor or SELinux and runtime before evaluating escape. Root inside a container with user namespaces may map to an unprivileged host UID. The visible UID alone does not define the real boundary.

1
2
3
cat /proc/1/status | grep -E 'Cap|Seccomp'
lsns
findmnt

Docker Security

Access to the Docker daemon is often more valuable than root inside a single container. The Docker daemon usually runs with high host privilege and accepts operations that create containers, mounts and namespaces. Membership in the docker group or access to docker.sock may allow host filesystem mounts and privileged workloads. I check the socket, rootless context, remote daemon exposure, API access and security profile before testing a host mount. Root inside a container does not equal root on the host. The boundary breaks when capabilities, mounts, devices, sockets or kernel exposure allow escape.

1
2
ls -l /var/run/docker.sock
docker info

References

This post is licensed under CC BY 4.0 by the author.