Operator On The Wire
← Back to Knowledge Base
OOTW / Chapter II - Local / 02. Containers

Containers

Containers are process isolation, not full machines.

Container platforms and runtimes such as Docker, containerd, CRI-O, LXC, and Kubernetes-managed workloads isolate processes with Linux kernel features such as namespaces, cgroups, capabilities, seccomp, AppArmor, SELinux, and filesystem mounts. The container still shares the host kernel.

That is the security model:

separate process view
separate filesystem view
limited capabilities
limited device access
shared host kernel

Container escape happens when that isolation boundary is weakened, misconfigured, or bypassed.

We do not begin by hunting random kernel exploits. We begin by mapping the boundary. Once the boundary is mapped, the escape path is usually obvious: socket control, host mount write access, excessive capabilities, shared namespaces, runtime API access, or Kubernetes API abuse.


Core Model

Docker isolation commonly uses:

ControlPurpose
NamespacesGive the process its own view of PIDs, mounts, network, IPC, UTS, and users.
CgroupsLimit and account for CPU, memory, PIDs, and devices.
CapabilitiesSplit root privileges into smaller pieces.
SeccompRestrict available syscalls.
AppArmor / SELinuxEnforce mandatory access controls.
MountsShape which host paths appear inside the container.
User namespacesMap container users to different host users.

Root inside a container is not automatically root on the host.

Root inside a poorly configured container may become host root if the container has dangerous privileges, host mounts, Docker socket access, host namespaces, or a kernel escape.


Escape Mindset

Container escape is usually not magic.

Most escapes come from one of these conditions:

  • Docker socket mounted inside the container
  • Docker API exposed over TCP
  • --privileged container
  • Dangerous Linux capabilities
  • Host filesystem mounted into the container
  • Host PID/network/mount namespace shared
  • Writable sensitive host paths
  • Container runtime vulnerability
  • Host kernel vulnerability
  • Kubernetes service account or node-level misconfiguration

The practical question is:

What host control surface is reachable from inside this container?

That question keeps the workflow grounded. We are not asking whether the process is "in Docker" as trivia. We are asking whether the process can reach something that controls the host, runtime, node, or cluster.


Enumeration Order

Use this order:

  1. Confirm containerization.
  2. Identify runtime and orchestrator clues.
  3. Inspect identity and capabilities.
  4. Inspect mounts.
  5. Inspect namespaces.
  6. Inspect network.
  7. Search for Docker/containerd sockets.
  8. Search for secrets and service account tokens.
  9. Check for host filesystem exposure.
  10. Check kernel and runtime versions.
  11. Map findings to escape techniques.

High-Value Findings

Use this as the mental map for the whole section.

FindingWhy It Matters
Docker socketLocal control plane for the Docker daemon. Usually host-root equivalent.
Docker API on 2375Network-exposed Docker control plane. Critical when unauthenticated.
Runtime socketscontainerd / CRI-O control plane access. Docker is not the only runtime.
Host root mountDirect read/write path into the host filesystem.
Writable sensitive mountMay allow credential theft, service modification, SUID drops, or persistence.
--privilegedRemoves many container isolation restrictions.
Dangerous capabilitiesAdds back pieces of root that containers normally lose.
Host PID/network namespaceMakes host processes or services reachable from the container.
Kubernetes tokenMay allow API-driven pod, secret, or node abuse.
Kernel/runtime bugCan break the boundary when the host is vulnerable and controls permit it.

Docker Socket

/var/run/docker.sock

Access to the Docker socket is usually equivalent to root on the Docker host. The Docker daemon runs with host-level privileges and can start new containers with host mounts.

Exposed Docker API

tcp/2375
tcp/2376

Unauthenticated Docker API on 2375 is critical. TLS-protected Docker API commonly uses 2376, but certificate handling still matters.

Privileged Container

Privileged containers disable many of the normal restrictions and often expose host devices and capabilities.

Indicators:

capsh --print
cat /proc/self/status | grep Cap
ls -la /dev

Host Mounts

Host directories mounted into containers can expose secrets, source code, Docker data, credentials, or writable paths.

Check:

mount
cat /proc/self/mountinfo
findmnt

Dangerous Capabilities

Capabilities such as CAP_SYS_ADMIN, CAP_SYS_PTRACE, CAP_DAC_READ_SEARCH, CAP_SYS_MODULE, and CAP_SYS_CHROOT are high value.

Shared Namespaces

Host PID or network namespace sharing can make host processes and services visible.

Check:

ps aux
ip addr
lsns
readlink /proc/1/ns/*
readlink /proc/self/ns/*

Common Tools

Use tools to speed up enumeration, then verify manually.

deepce
CDK
amicontained
linpeas
container-escape-check
kubectl
crictl
ctr
docker
nerdctl

Tools are not a replacement for understanding the preconditions. They tell us where to look.

The rule is simple:

tool finding -> manual confirmation -> scoped proof

If a tool says "Docker socket found", we still check the path, permissions, and daemon access. If a tool says "CAP_SYS_ADMIN", we still check whether mounting or namespace abuse is actually possible.


Remediation Themes

Strong container security comes from least privilege:

  • Do not mount the Docker socket into application containers.
  • Do not expose Docker API without authentication and TLS.
  • Avoid --privileged.
  • Drop all capabilities, then add only what is required.
  • Use read-only root filesystems where possible.
  • Use non-root users inside containers.
  • Enable user namespace remapping where appropriate.
  • Keep seccomp, AppArmor, or SELinux profiles enabled.
  • Avoid host PID, host network, and host IPC unless required.
  • Keep host paths out of containers unless required.
  • Mount host paths read-only when possible.
  • Keep host kernel and runtime patched.
  • Treat container logs, environment variables, and mounted secrets as sensitive.

The safest design assumes container compromise can happen and limits what the compromised container can reach.