overview.md (10123B)
1 --- 2 title: "Namespaces" 3 section: "Linux" 4 sectionSlug: "linux-hardening" 5 sourcePath: "src/linux-hardening/containers-namespaces/container-security/protections/namespaces/README.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/containers-namespaces/container-security/protections/namespaces/README.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: true 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Namespaces 14 15 Namespaces are the kernel feature that makes a container feel like "its own machine" even though it is really just a host process tree. They do not create a new kernel and they do not virtualize everything, but they do let the kernel present different views of selected resources to different groups of processes. That is the core of the container illusion: the workload sees a filesystem, process table, network stack, hostname, IPC resources, and user/group identity model that appear local, even though the underlying system is shared. <sup>[[1]](#references)</sup> 16 17 This is why namespaces are the first concept most people encounter when they learn how containers work. At the same time, they are one of the most commonly misunderstood concepts because readers often assume that "has namespaces" means "is safely isolated". In reality, a namespace only isolates the specific class of resources it was designed for. A process can have a private PID namespace and still be dangerous because it has a writable host bind mount. It can have a private network namespace and still be dangerous because it retains `CAP_SYS_ADMIN` and runs without seccomp. Namespaces are foundational, but they are only one layer in the final boundary. 18 19 ## Namespace Types 20 21 Linux containers commonly rely on several namespace types at the same time. The **mount namespace** gives the process a separate mount table and therefore a controlled filesystem view. The **PID namespace** changes process visibility and numbering so the workload sees its own process tree. The **network namespace** isolates interfaces, routes, sockets, and firewall state. The **IPC namespace** isolates SysV IPC and POSIX message queues. The **UTS namespace** isolates hostname and NIS domain name. The **user namespace** remaps user and group IDs so that root inside the container does not necessarily mean root on the host. The **cgroup namespace** virtualizes the visible cgroup hierarchy, and the **time namespace** virtualizes selected clocks in newer kernels. <sup>[[1]](#references)</sup> <sup>[[2]](#references)</sup> 22 23 Each of these namespaces solves a different problem. This is why practical container security analysis often comes down to checking **which namespaces are isolated** and **which ones have been deliberately shared with the host**. 24 25 ## Host Namespace Sharing 26 27 Many container breakouts do not begin with a kernel vulnerability. They begin with an operator deliberately weakening the isolation model. The examples `--pid=host`, `--network=host`, and `--userns=host` are **Docker/Podman-style CLI flags** used here as concrete examples of host namespace sharing. Other runtimes express the same idea differently. In Kubernetes the equivalents usually appear as Pod settings such as `hostPID: true`, `hostNetwork: true`, or `hostIPC: true`. In lower-level runtime stacks such as containerd or CRI-O, the same behavior is often reached through the generated OCI runtime configuration rather than through a user-facing flag with the same name. In all of these cases, the result is similar: the workload no longer receives the default isolated namespace view. <sup>[[2]](#references)</sup> <sup>[[3]](#references)</sup> 28 29 This is why namespace reviews should never stop at "the process is in some namespace". The important question is whether the namespace is private to the container, shared with sibling containers, or joined directly to the host. In Kubernetes the same idea appears with flags such as `hostPID`, `hostNetwork`, and `hostIPC`. The names change between platforms, but the risk pattern is the same: a shared host namespace makes the container's remaining privileges and reachable host state much more meaningful. 30 31 ## Inspection 32 33 The simplest overview is: 34 35 ```bash 36 ls -l /proc/self/ns 37 ``` 38 39 Each entry is a symbolic link with an inode-like identifier. If two processes point to the same namespace identifier, they are in the same namespace of that type. That makes `/proc` a very useful place to compare the current process with other interesting processes on the machine. 40 41 These quick commands are often enough to start: 42 43 ```bash 44 readlink /proc/self/ns/mnt 45 readlink /proc/self/ns/pid 46 readlink /proc/self/ns/net 47 readlink /proc/1/ns/mnt 48 ``` 49 50 From there, the next step is to compare the container process with host or neighboring processes and determine whether a namespace is actually private or not. 51 52 ### Enumerating Namespace Instances From The Host 53 54 When you already have host access and want to understand how many distinct namespaces of a given type exist, `/proc` gives a quick inventory: 55 56 ```bash 57 sudo find /proc -maxdepth 3 -type l -name mnt -exec readlink {} \; 2>/dev/null | sort -u 58 sudo find /proc -maxdepth 3 -type l -name pid -exec readlink {} \; 2>/dev/null | sort -u 59 sudo find /proc -maxdepth 3 -type l -name net -exec readlink {} \; 2>/dev/null | sort -u 60 sudo find /proc -maxdepth 3 -type l -name ipc -exec readlink {} \; 2>/dev/null | sort -u 61 sudo find /proc -maxdepth 3 -type l -name uts -exec readlink {} \; 2>/dev/null | sort -u 62 sudo find /proc -maxdepth 3 -type l -name user -exec readlink {} \; 2>/dev/null | sort -u 63 sudo find /proc -maxdepth 3 -type l -name cgroup -exec readlink {} \; 2>/dev/null | sort -u 64 sudo find /proc -maxdepth 3 -type l -name time -exec readlink {} \; 2>/dev/null | sort -u 65 ``` 66 67 If you want to find which processes belong to one specific namespace identifier, switch from `readlink` to `ls -l` and grep for the target namespace number: 68 69 ```bash 70 sudo find /proc -maxdepth 3 -type l -name mnt -exec ls -l {} \; 2>/dev/null | grep <ns-number> 71 ``` 72 73 These commands are useful because they let you answer whether a host is running one isolated workload, many isolated workloads, or a mixture of shared and private namespace instances. 74 75 ### Entering A Target Namespace 76 77 When the caller has sufficient privilege, `nsenter` is the standard way to join another process's namespace: 78 79 ```bash 80 nsenter -m TARGET_PID --pid /bin/bash # mount 81 nsenter -t TARGET_PID --pid /bin/bash # pid 82 nsenter -n TARGET_PID --pid /bin/bash # network 83 nsenter -i TARGET_PID --pid /bin/bash # ipc 84 nsenter -u TARGET_PID --pid /bin/bash # uts 85 nsenter -U TARGET_PID --pid /bin/bash # user 86 nsenter -C TARGET_PID --pid /bin/bash # cgroup 87 nsenter -T TARGET_PID --pid /bin/bash # time 88 ``` 89 90 The point of listing these forms together is not that every assessment needs all of them, but that namespace-specific post-exploitation often becomes much easier once the operator knows the exact entry syntax instead of remembering only the all-namespaces form. 91 92 ## Pages 93 94 The following pages explain each namespace in more detail: 95 96 [Mount Namespace](/hacktricks/linux-hardening/containers-namespaces/container-security/protections/namespaces/mount-namespace) 97 98 [Pid Namespace](/hacktricks/linux-hardening/containers-namespaces/container-security/protections/namespaces/pid-namespace) 99 100 [Network Namespace](/hacktricks/linux-hardening/containers-namespaces/container-security/protections/namespaces/network-namespace) 101 102 [Ipc Namespace](/hacktricks/linux-hardening/containers-namespaces/container-security/protections/namespaces/ipc-namespace) 103 104 [Uts Namespace](/hacktricks/linux-hardening/containers-namespaces/container-security/protections/namespaces/uts-namespace) 105 106 [User Namespace](/hacktricks/linux-hardening/containers-namespaces/container-security/protections/namespaces/user-namespace) 107 108 [Cgroup Namespace](/hacktricks/linux-hardening/containers-namespaces/container-security/protections/namespaces/cgroup-namespace) 109 110 [Time Namespace](/hacktricks/linux-hardening/containers-namespaces/container-security/protections/namespaces/time-namespace) 111 112 As you read them, keep two ideas in mind. First, each namespace isolates only one kind of view. Second, a private namespace is useful only if the rest of the privilege model still makes that isolation meaningful. 113 114 ## Runtime Defaults 115 116 | Runtime / platform | Default namespace posture | Common manual weakening | 117 | --- | --- | --- | 118 | Docker Engine | New mount, PID, network, IPC, and UTS namespaces by default; user namespaces are available but not enabled by default in standard rootful setups | `--pid=host`, `--network=host`, `--ipc=host`, `--uts=host`, `--userns=host`, `--cgroupns=host`, `--privileged` | 119 | Podman | New namespaces by default; rootless Podman automatically uses a user namespace; cgroup namespace defaults depend on cgroup version | `--pid=host`, `--network=host`, `--ipc=host`, `--uts=host`, `--userns=host`, `--cgroupns=host`, `--privileged` | 120 | Kubernetes | Pods do **not** share host PID, network, or IPC by default; Pod networking is private to the Pod, not to each individual container; user namespaces are opt-in via `spec.hostUsers: false` on supported clusters | `hostPID: true`, `hostNetwork: true`, `hostIPC: true`, `spec.hostUsers: true` / omitting user-namespace opt-in, privileged workload settings | 121 | containerd / CRI-O under Kubernetes | Usually follow Kubernetes Pod defaults | same as Kubernetes row; direct CRI/OCI specs can also request host namespace joins | 122 123 The main portability rule is simple: the **concept** of host namespace sharing is common across runtimes, but the **syntax** is runtime-specific. 124 125 ## References 126 127 - [1] [namespaces(7) - Linux manual page](https://man7.org/linux/man-pages/man7/namespaces.7.html) 128 - [2] [Open Container Initiative - Linux container namespaces](https://github.com/opencontainers/runtime-spec/blob/main/config-linux.md#namespaces) 129 - [3] [Kubernetes API Reference - PodSpec host namespaces](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec)