daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

masked-paths.md (7278B)


      1 ---
      2 title: "Masked Paths"
      3 section: "Linux"
      4 sectionSlug: "linux-hardening"
      5 sourcePath: "src/linux-hardening/containers-namespaces/container-security/protections/masked-paths.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/containers-namespaces/container-security/protections/masked-paths.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Masked Paths
     14 
     15 Masked paths are runtime protections that hide especially sensitive kernel-facing filesystem locations from the container by bind-mounting over them or otherwise making them inaccessible. The OCI runtime specification defines `maskedPaths` as absolute paths that must not be readable inside the container. <sup>[[1]](#references)</sup>
     16 
     17 This matters because many container escapes and host-impacting tricks start by reading or writing special files under `/proc` or `/sys`. If those locations are masked, the attacker loses direct access to a useful part of the kernel control surface even after gaining code execution inside the container.
     18 
     19 ## Operation
     20 
     21 Runtimes commonly mask selected paths such as:
     22 
     23 - `/proc/kcore`
     24 - `/proc/keys`
     25 - `/proc/latency_stats`
     26 - `/proc/timer_list`
     27 - `/proc/sched_debug`
     28 - `/sys/firmware`
     29 
     30 The exact list depends on the runtime and host configuration. The important property is that the path becomes inaccessible or replaced from the container's point of view even though it still exists on the host.
     31 
     32 ## Lab
     33 
     34 Inspect the masked-path configuration exposed by Docker:
     35 
     36 ```bash
     37 docker inspect <container> | jq '.[0].HostConfig.MaskedPaths'
     38 ```
     39 
     40 Inspect the actual mount behavior inside the workload:
     41 
     42 ```bash
     43 mount | grep -E '/proc|/sys'
     44 ls -ld /proc/kcore /proc/keys /sys/firmware 2>/dev/null
     45 ```
     46 
     47 ## Security Impact
     48 
     49 Masking does not create the main isolation boundary, but it removes several high-value post-exploitation targets. Without masking, a compromised container may be able to inspect kernel state, read sensitive process or keying information, or interact with procfs/sysfs objects that should never have been visible to the application.
     50 
     51 ## Misconfigurations
     52 
     53 The main mistake is unmasking broad classes of paths for convenience or debugging. In Podman this may appear as `--security-opt unmask=ALL` or targeted unmasking. In Kubernetes, overly broad proc exposure may appear through `procMount: Unmasked`. Another serious problem is exposing host `/proc` or `/sys` through a bind mount, which bypasses the idea of a reduced container view entirely. <sup>[[2]](#references)</sup> <sup>[[3]](#references)</sup>
     54 
     55 ## Abuse
     56 
     57 If masking is weak or absent, start by identifying which sensitive procfs/sysfs paths are directly reachable:
     58 
     59 ```bash
     60 ls -ld /proc/kcore /proc/keys /proc/timer_list /sys/firmware 2>/dev/null   # Check whether paths that are usually masked are accessible at all
     61 mount | grep -E '/proc|/sys'                                                # Review whether procfs/sysfs mounts look container-scoped or suspiciously host-like
     62 ```
     63 
     64 If a supposedly masked path is accessible, inspect it carefully:
     65 
     66 ```bash
     67 head -n 20 /proc/timer_list 2>/dev/null   # Scheduler / timer internals, useful for host fingerprinting and confirming kernel data exposure
     68 cat /proc/keys 2>/dev/null | head         # In-kernel keyring information; may expose keys, key descriptions, or service relationships
     69 ls -la /sys/firmware 2>/dev/null          # Firmware / boot environment metadata; useful for host fingerprinting and low-level platform recon
     70 zcat /proc/config.gz 2>/dev/null | head   # Kernel build configuration; useful to confirm enabled subsystems and exploit preconditions
     71 head -n 50 /proc/sched_debug 2>/dev/null  # Scheduler and process metadata; may reveal host tasks and cgroup relationships
     72 ```
     73 
     74 What these commands can reveal:
     75 
     76 - `/proc/timer_list` can expose host timer and scheduler data. This is mostly a reconnaissance primitive, but it confirms that the container can read kernel-facing information that is normally hidden.
     77 - `/proc/keys` is much more sensitive. Depending on the host configuration, it may reveal keyring entries, key descriptions, and relationships between host services using the kernel keyring subsystem.
     78 - `/sys/firmware` helps identify boot mode, firmware interfaces, and platform details that are useful for host fingerprinting and for understanding whether the workload is seeing host-level state.
     79 - `/proc/config.gz` may reveal the running kernel configuration, which is valuable for matching public kernel exploit prerequisites or understanding why a specific feature is reachable.
     80 - `/proc/sched_debug` exposes scheduler state and often bypasses the intuitive expectation that the PID namespace should hide unrelated process information completely.
     81 
     82 Interesting results include direct reads from those files, evidence that the data belongs to the host rather than to a constrained container view, or access to other procfs/sysfs locations that are commonly masked by default.
     83 
     84 ## Checks
     85 
     86 The point of these checks is to determine which paths the runtime intentionally hid and whether the current workload still sees a reduced kernel-facing filesystem.
     87 
     88 ```bash
     89 docker inspect <container> | jq '.[0].HostConfig.MaskedPaths'   # Runtime-declared masked paths
     90 mount | grep -E '/proc|/sys'                                    # Actual procfs/sysfs mount layout
     91 ls -ld /proc/kcore /proc/keys /proc/timer_list /sys/firmware 2>/dev/null
     92 ```
     93 
     94 What is interesting here:
     95 
     96 - A long masked-path list is normal in hardened runtimes.
     97 - Missing masking on sensitive procfs entries deserves closer inspection.
     98 - If a sensitive path is accessible and the container also has strong capabilities or broad mounts, the exposure matters more.
     99 
    100 ## Runtime Defaults
    101 
    102 | Runtime / platform | Default state | Default behavior | Common manual weakening |
    103 | --- | --- | --- | --- |
    104 | Docker Engine | Enabled by default | Docker defines a default masked path list | exposing host proc/sys mounts, `--privileged` |
    105 | Podman | Enabled by default | Podman applies default masked paths unless unmasked manually | `--security-opt unmask=ALL`, targeted unmasking, `--privileged` |
    106 | Kubernetes | Inherits runtime defaults | Uses the underlying runtime's masking behavior unless Pod settings weaken proc exposure | `procMount: Unmasked`, privileged workload patterns, broad host mounts |
    107 | containerd / CRI-O under Kubernetes | Runtime default | Usually applies OCI/runtime masked paths unless overridden | direct runtime config changes, same Kubernetes weakening paths |
    108 
    109 Masked paths are usually present by default. The main operational problem is not absence from the runtime, but deliberate unmasking or host bind mounts that negate the protection.
    110 
    111 ## References
    112 
    113 - [1] [Open Container Initiative - Linux container configuration: Masked Paths](https://github.com/opencontainers/runtime-spec/blob/main/config-linux.md#masked-paths)
    114 - [2] [Podman documentation - `podman run` security options](https://docs.podman.io/en/latest/markdown/podman-run.1.html#security-opt-option)
    115 - [3] [Kubernetes Documentation - ProcMount](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-proc-mount-type-for-a-container)