F-7.2: Privileged Port Restriction Bypass¶
Classification¶
- Severity: Medium
- CVSS Vector: Network / Low Complexity / Requires Network Access
- Affected Versions: NFSv2, NFSv3 (servers using
secureexport option) - Prerequisite: Access to a trusted host (SSH, container runtime, or CAP_NET_BIND_SERVICE)
Summary¶
NFS servers can restrict connections to privileged source ports (<1024) via the secure export option (Linux default) or nfs_portmon (Solaris). The assumption is that only root can bind to these ports, preventing unprivileged users from running rogue NFS clients. This assumption is false on modern systems — multiple bypass vectors exist.
Technical detail¶
The security model¶
The server rejects RPC calls from source ports >= 1024. The theory: a non-root user on a trusted machine cannot forge NFS credentials because they can't bind to a privileged port.
Bypass vector 1: CAP_NET_BIND_SERVICE¶
Linux capabilities allow granting port-binding privilege to any binary without full root:
# Grant bind capability to a custom NFS client
sudo setcap 'CAP_NET_BIND_SERVICE+ep' ./nfs_client
# Now any user can run it and bind to privileged ports
./nfs_client --uid 0 --gid 0 target:/export
Any binary with this capability can bind to port <1024. If the attacker finds any such binary on a trusted host, they can use it as a springboard.
Bypass vector 2: SSH port forwarding¶
A non-root user with SSH access to a trusted host can forward a privileged port:
# On attacker machine (where you are root):
# Forward local port 800 -> trusted_host -> nfs_server:2049
ssh -L 800:nfs_server:2049 user@trusted_host
# Now mount via the tunnel — traffic arrives at NFS server from
# trusted_host's IP on a privileged port
mount -t nfs -o port=800,mountport=800 localhost:/export /mnt
The NFS server sees the connection from trusted_host on a privileged port — both the IP check and the port check pass.
Bypass vector 3: Docker containers¶
Since Docker 20.03, unprivileged ports start at 0 inside containers. Any containerized process can bind to ports <1024:
# Inside a Docker container on a trusted host
docker run --rm -it --net=host alpine
# Port restriction is meaningless — bind to any port
Bypass vector 4: Non-Unix clients¶
Windows has no concept of privileged ports. Any Windows program can bind to any port. The secure option is meaningless against Windows NFS clients.
Bypass vector 5: insecure export option¶
Some administrators explicitly set insecure to support broken clients:
This disables the port check entirely. Combined with no_root_squash, this grants full root access to anyone who can reach the port.
Impact¶
- Unprivileged users on trusted hosts can forge NFS credentials
- The privileged port restriction provides a false sense of security
- Administrators may skip Kerberos deployment believing port checks are sufficient
Detection¶
- Monitor for
insecurein/etc/exports - Audit binaries with
CAP_NET_BIND_SERVICE:getcap -r / 2>/dev/null | grep net_bind - Monitor SSH port forwards on trusted NFS clients
- Check Docker daemon availability on NFS clients
Remediation¶
- Don't rely on port restrictions — they are a speed bump, not a barrier
- Use Kerberos (
sec=krb5p) — makes port checks irrelevant - Never combine
insecurewithno_root_squash - Audit trusted hosts for Docker, capabilities, and SSH access