Securing rpcbind: How Unauthenticated RPC Registration Exposes NFS Infrastructure
Introduction
If you're running NFS (Network File System) in a Kubernetes cluster or any networked environment, there's a small daemon quietly listening on port 111 that could be the weakest link in your storage security: rpcbind (formerly known as portmap).
rpcbind acts as the phone book for RPC (Remote Procedure Call) services. When an NFS client wants to mount a remote filesystem, it first calls rpcbind to ask: "Where is the NFS server listening?" rpcbind looks up the registered port and hands it back. Simple, elegant — and by default, completely unauthenticated.
This post breaks down a high-severity vulnerability (V-007) discovered in an NFS utilities deployment configuration, explains how an attacker could exploit it, and walks through the fix and best practices to harden your RPC infrastructure.
The Vulnerability Explained
What Is rpcbind and Why Does It Matter?
rpcbind is a critical component of the NFSv3 stack. It maps RPC program numbers to network port numbers, acting as a dynamic service registry. Any RPC service — NFS, NLM (Network Lock Manager), NSM (Network Status Monitor) — must register itself with rpcbind before clients can discover it.
The problem? By default, rpcbind accepts PMAP_SET registration calls from any network source without authentication.
The Core Weakness
The vulnerability was confirmed in storage/nfs-utils/rpcbind/files/services at line 3, where rpcbind is deployed and exposed on port 111 across all network interfaces. The scanner found:
- ✗ No firewall rules restricting access to port 111
- ✗ No TCP wrappers configuration (
/etc/hosts.allow//etc/hosts.deny) - ✗ No authentication mechanism for
PMAP_SETcalls - ✗ No network policy limiting which pods or hosts can reach the rpcbind port
How Could an Attacker Exploit This?
The attack is elegant in its simplicity. Here's a step-by-step exploitation scenario:
Attack Scenario: RPC Service Hijacking
1. Attacker gains network access to the cluster (e.g., via a compromised pod)
2. Attacker sends a crafted PMAP_SET packet to port 111 on the rpcbind host
3. Attacker registers their malicious process under NFS program number 100003
4. Legitimate NFS clients query rpcbind for the NFS service location
5. rpcbind returns the attacker's registered port instead of the real NFS server
6. NFS clients connect to the attacker's service and send file operation requests
7. Attacker intercepts, reads, modifies, or corrupts file data in transit
A minimal proof-of-concept registration using Python's rpc libraries might look like:
# Conceptual example — for educational purposes only
import socket
import struct
# PMAP_SET: Register a fake NFS service (program 100003) on port 9999
# This would redirect NFS clients to an attacker-controlled port
pmap_set_call = build_rpc_call(
program=100000, # rpcbind program number
procedure=1, # PMAP_SET procedure
args={
'prog': 100003, # NFS program number
'vers': 3,
'prot': 6, # TCP
'port': 9999 # Attacker's malicious listener
}
)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('target-rpcbind-host', 111))
sock.send(pmap_set_call)
# If successful, NFS clients now get redirected to port 9999
Real-World Impact
The consequences of a successful RPC hijack are severe:
| Impact | Description |
|---|---|
| Data Interception | Attacker reads sensitive files from NFS mounts |
| Data Corruption | Attacker modifies files mid-transit |
| Denial of Service | Legitimate NFS services become unreachable |
| Privilege Escalation | Manipulated files (e.g., /etc/sudoers, SSH keys) could grant higher access |
| Persistence | Attacker maintains access by keeping malicious service registered |
In a Kubernetes environment, NFS volumes are often shared across multiple pods and namespaces. A single rpcbind compromise could affect the entire cluster's persistent storage.
The Fix
What Changed
The fix introduces a critical security notice in the README.md for the nfs-utils extension, alongside a corresponding update to rpcbind.yaml:
diff --git a/storage/nfs-utils/README.md b/storage/nfs-utils/README.md
--- a/storage/nfs-utils/README.md
+++ b/storage/nfs-utils/README.md
@@ -1,5 +1,11 @@
# nfs-utils
+> **NOTE: Security Consideration**
+>
+> `rpcbind` listens on all network interfaces by default. This is required for remote NFS
+> clients to discover RPC services. Ensure that rpcbind is only exposed on trusted networks
+> and use host-level firewalling or Kubernetes network policies to restrict access to port 111.
+
This extension provides `rpcbind` and `rpc.statd` daemons for NFSv3 file locking support.
Why This Matters
This fix does two important things:
-
Acknowledges the architectural reality: rpcbind must listen broadly to serve NFS clients — you can't simply bind it to localhost. The note is honest about this constraint.
-
Directs operators to the correct mitigation layer: Since rpcbind itself lacks built-in authentication for
PMAP_SET, the defense must happen at the network layer. The fix explicitly calls this out and points to the right tools.
The Deeper Fix: Network-Level Controls
The documentation fix is the first step. The real remediation happens when operators implement the recommended network controls. Here's what that looks like in practice:
Option 1: iptables / nftables Host Firewall
# Allow rpcbind only from trusted NFS client subnet
iptables -A INPUT -p tcp --dport 111 -s 10.0.1.0/24 -j ACCEPT
iptables -A INPUT -p udp --dport 111 -s 10.0.1.0/24 -j ACCEPT
# Drop all other rpcbind traffic
iptables -A INPUT -p tcp --dport 111 -j DROP
iptables -A INPUT -p udp --dport 111 -j DROP
# Also restrict PMAP_SET (registration) to localhost only
# This prevents remote service registration entirely
iptables -A INPUT -p tcp --dport 111 ! -s 127.0.0.1 -m string \
--algo bm --string "PMAP_SET" -j DROP
Option 2: Kubernetes NetworkPolicy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-rpcbind
namespace: storage
spec:
podSelector:
matchLabels:
app: nfs-server
policyTypes:
- Ingress
ingress:
# Allow rpcbind only from NFS client pods
- from:
- podSelector:
matchLabels:
role: nfs-client
- namespaceSelector:
matchLabels:
nfs-access: "true"
ports:
- protocol: TCP
port: 111
- protocol: UDP
port: 111
Option 3: TCP Wrappers (Legacy but Effective)
# /etc/hosts.allow
rpcbind: 10.0.1.0/255.255.255.0 # Trusted NFS client subnet
rpcbind: 127.0.0.1 # Localhost always allowed
# /etc/hosts.deny
rpcbind: ALL # Deny everything else
Option 4: rpcbind -h Flag (Bind to Specific Interface)
# Start rpcbind bound only to the internal network interface
# instead of all interfaces (0.0.0.0)
rpcbind -h 10.0.1.100
# In systemd unit or container args:
ExecStart=/sbin/rpcbind -f -w -h 10.0.1.100
Prevention & Best Practices
1. Apply the Principle of Least Network Exposure
RPC services like rpcbind should never be exposed to the public internet or untrusted networks. Treat port 111 like you would a database port — strictly firewalled.
Internet → [Firewall: DENY 111] → Internal Network → [Firewall: ALLOW 111 from trusted] → NFS Host
2. Prefer NFSv4 Over NFSv3 Where Possible
NFSv4 does not use rpcbind for its primary port — it uses a well-known port (2049) directly. This eliminates the rpcbind attack surface entirely for the main data path.
# NFSv4 mount — no rpcbind dependency for the mount itself
mount -t nfs4 -o proto=tcp nfs-server:/export /mnt/data
# NFSv3 mount — requires rpcbind to be accessible
mount -t nfs -o vers=3 nfs-server:/export /mnt/data
3. Audit Registered RPC Services Regularly
Use rpcinfo to periodically verify that only expected services are registered:
# List all registered RPC services
rpcinfo -p <nfs-host>
# Expected output for a clean NFS server:
# program vers proto port service
# 100000 4 tcp 111 portmapper
# 100000 3 tcp 111 portmapper
# 100003 3 tcp 2049 nfs
# 100021 1 tcp 32803 nlockmgr
# Alert if unexpected program numbers appear!
4. Use Container Security Contexts in Kubernetes
securityContext:
runAsNonRoot: true
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE # Only if binding to privileged port
5. Monitor for Anomalous PMAP_SET Calls
Set up network monitoring to alert on PMAP_SET calls originating from unexpected sources:
# Falco rule example
- rule: Unexpected RPC Service Registration
desc: Detect PMAP_SET calls to rpcbind from non-localhost sources
condition: >
evt.type = connect and
fd.sport = 111 and
not fd.sip in (trusted_nfs_hosts)
output: "Unexpected rpcbind connection (source=%fd.cip dest=%fd.sip)"
priority: WARNING
Security Standards & References
This vulnerability maps to several well-known security frameworks:
| Standard | Reference |
|---|---|
| CWE | CWE-306: Missing Authentication for Critical Function |
| CWE | CWE-284: Improper Access Control |
| NIST | SP 800-123: Guide to General Server Security |
| CIS | CIS Benchmarks for Linux — Network Services Hardening |
| OWASP | A01:2021 – Broken Access Control |
Key Takeaways
The Vulnerability at a Glance
┌─────────────────────────────────────────────────────┐
│ VULNERABILITY: Unauthenticated rpcbind Registration │
│ SEVERITY: HIGH │
│ FILE: storage/nfs-utils/rpcbind/files/services:3 │
│ │
│ ATTACK VECTOR: Network → Port 111 → PMAP_SET │
│ IMPACT: NFS service hijacking, data interception │
│ │
│ FIX: Document + enforce network-level restrictions │
└─────────────────────────────────────────────────────┘
What We Learned
-
Protocol-level authentication gaps require network-level mitigations. When a protocol doesn't support authentication natively, your defense-in-depth strategy must compensate at the network layer.
-
Documentation is a security control. Explicitly calling out dangerous defaults in README files and deployment manifests prevents operators from unknowingly deploying insecure configurations.
-
Upgrade paths matter. NFSv4's elimination of rpcbind dependency for the primary mount path is a meaningful security improvement — evaluate whether your use case can migrate.
-
Least privilege applies to network exposure too. Every open port is an attack surface. Port 111 should be treated with the same caution as any other privileged service port.
Security in infrastructure components like NFS is often overlooked because these services "just work" — but that reliability can mask decades-old design decisions made when network trust models were very different. Taking the time to audit and harden these foundational services is exactly the kind of security hygiene that prevents serious breaches.
This vulnerability was automatically detected and fixed by OrbisAI Security. Automated security scanning helps catch configuration-level vulnerabilities that traditional SAST tools often miss.