Skip to content

F-2.9: WebNFS Public File Handle (MOUNT Bypass)

Classification

  • Severity: Critical
  • CVSS Vector: Network / Low Complexity / No Auth Required
  • Affected Versions: NFSv2, NFSv3 (servers with WebNFS enabled)
  • RFC Reference: RFC 2054 §5, RFC 2055 §5, RFC 2055 §6.3, RFC 2055 §10, RFC 2224 §9, RFC 2623 §2.6
  • Prerequisite: Server has WebNFS enabled (Solaris public share option, NetApp nfs.webnfs.enable, embedded RTOS)

Summary

WebNFS defines a well-known "public" file handle that any client can construct and use without the MOUNT protocol. For NFSv3, the public handle is zero-length; for NFSv2, it is 32 bytes of zeros. A client presenting this handle bypasses all MOUNT-layer access control: export ACLs, hostname restrictions, privileged-port checks, and auth flavor negotiation. Combined with multi-component LOOKUP, a single RPC can traverse the entire server filesystem tree.

Technical detail

The public file handle

Per RFC 2054 §5:

"A WebNFS client can use the public filehandle as an initial filehandle rather than using the MOUNT protocol."

  • NFSv3: Zero-length handle (the fhandle3 opaque with length 0)
  • NFSv2: 32 bytes of all zeros (the fixed fhandle type)

RFC 2623 §2.6 explicitly warns: "WebNFS clients that use the public file handle lookup will not go through the MOUNT protocol to acquire initial file handle of the NFS file system. Enforcing access control via the MOUNT protocol is going to be of little use."

Multi-component LOOKUP (MCL)

When used with the public handle, LOOKUP accepts a full pathname instead of a single component (RFC 2054 §6.1):

  • Absolute paths starting with "/" are "evaluated relative to the server's root directory" -- not the export root. A single LOOKUP 0x0 "/etc/shadow" reaches the absolute filesystem root if the server supports it.
  • Relative paths with ".." traverse upward. RFC 2224 §9 warns: "a path that includes multiple occurrences of '../' may locate a filesystem outside of the exported filesystem associated with the public filehandle."
  • Export-spanning: RFC 2055 §6.3 states the server may cross export boundaries during MCL evaluation, unlike regular LOOKUP which is restricted from crossing mountpoints.
  • Symlink resolution: The server evaluates symlinks inline during MCL (RFC 2055 §6.2), which could be exploited for further traversal.

MOUNT bypass impact

The public handle bypasses every layer of MOUNT-based access control:

MOUNT Protection Bypassed? Why
Export ACLs (IP/hostname) Yes MOUNT is never called; handle is well-known
Auth flavor negotiation Yes No MNT response → no auth_flavors list
Privileged port check Yes Port check is on mountd, not nfsd
Export path validation Yes MCL with "/" starts at server root

WebNFS security negotiation (RFC 2755)

The SNEGO-MCL protocol (RFC 2755) allows unauthenticated enumeration of security mechanisms:

  • A LOOKUP with a 0x81 prefix byte returns the complete array of security mechanisms the server accepts for a path
  • No authentication required for the negotiation itself (RFC 2755 §5: "no mandatory security mechanisms are specified")
  • AUTH_TOOWEAK responses confirm path existence and reveal stronger auth requirements

Attack flow

1. Send GETATTR with zero-length handle (NFSv3) or all-zero handle (NFSv2)
   → NFS3_OK confirms WebNFS is enabled

2. Send LOOKUP with public handle + canonical path "/etc/shadow"
   → Returns file handle for /etc/shadow (absolute path, bypasses export root)

3. READ the returned handle with GID 42 (Debian shadow group)
   → Password hashes extracted in two RPCs, no MOUNT needed

Impact

  • Complete MOUNT bypass: No export ACL, no hostname check, no port check
  • Server root traversal: Absolute paths reach the entire filesystem
  • Single-RPC exploitation: MCL + READ = two RPCs from zero knowledge to data extraction
  • Invisible to mountd: No MOUNT calls means no rmtab entries, no showmount visibility
  • Strengthens F-2.7: Handles obtained via public handle work as bearer tokens from any IP

Detection (nfswolf)

The analyzer checks (src/engine/analyzer.rs): 1. GETATTR with zero-length handle (NFSv3) and all-zero handle (NFSv2) 2. On success, attempts multi-component LOOKUP for "etc/shadow" on both versions 3. Reports as Critical when the public handle is accepted

Remediation

  1. Disable WebNFS -- most servers do not need it:
  2. Solaris: remove public option from share
  3. NetApp: nfs.webnfs.enable off
  4. Linux knfsd: does not support WebNFS (not vulnerable)
  5. Use Kerberos (sec=krb5) -- the public handle still reaches nfsd, but Kerberos prevents UID spoofing for file access
  6. Network segmentation -- restrict access to NFS port 2049
Finding Relationship
F-2.1: Export Escape Export escape via handle construction; WebNFS achieves the same result without construction
F-2.7: NFS Daemon ACL Blindness Root cause -- nfsd never validates that the handle was issued by mountd
F-5.1: Export List Enumeration MOUNT EXPORT reveals ACLs; WebNFS bypasses MOUNT entirely