Back to Blog
high SEVERITY8 min read

Securing rpcbind: How Unauthenticated RPC Registration Exposes NFS Infrastructure

A high-severity vulnerability was discovered in an NFS utilities configuration where rpcbind (port 111) accepted RPC service registrations without any authentication, allowing any network-accessible attacker to register malicious services under legitimate RPC program numbers and redirect NFS clients. The fix adds critical security documentation and network isolation guidance, ensuring operators understand that rpcbind must be protected by host-level firewalling or Kubernetes network policies to

O
By orbisai0security
May 28, 2026

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_SET calls
  • ✗ 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:

  1. 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.

  2. 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

  1. 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.

  2. Documentation is a security control. Explicitly calling out dangerous defaults in README files and deployment manifests prevents operators from unknowingly deploying insecure configurations.

  3. 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.

  4. 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.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #1078

Related Articles

high

Shell Injection via Unsafe String Concatenation in gRPCurl Command Generation

A high-severity vulnerability was discovered in PaddleOCR's deployment configuration where model download URLs were specified using unencrypted `http://`, exposing users to man-in-the-middle attacks that could allow an attacker to intercept and replace model files with malicious ones. The fix upgrades all model download URLs to use `https://`, ensuring encrypted transmission and integrity of the downloaded files. This change is a critical security baseline for any application that downloads bina

high

Locking Down Docker: Preventing Privilege Escalation in Container Services

A high-severity privilege escalation vulnerability was discovered in a Docker Compose configuration where the `nginx` service lacked the `no-new-privileges` security option and was running with a writable root filesystem. These misconfigurations could allow a compromised container process to gain elevated permissions or download and execute malicious payloads. The fix applies defense-in-depth by adding `no-new-privileges:true`, enforcing a read-only root filesystem, and redirecting writable path

high

Thread-Safe Tokenization: Fixing strtok() Reentrancy in Game Script Parsing

A high-severity vulnerability was discovered in `lvl_script_commands.c` where the use of the non-reentrant `strtok()` function during level script parsing created conditions for memory corruption and potential arbitrary code execution. The fix replaces all `strtok()` calls with the thread-safe `strtok_r()` variant, eliminating shared global state that could be exploited through maliciously crafted level files. This change is part of a broader effort to harden the game's script parsing pipeline a

high

GPIO Bounds Checking: Fixing an Out-of-Bounds Access in py32ioexp Driver

A high-severity out-of-bounds access vulnerability was discovered and patched in the `py32ioexp` Linux GPIO expander driver. The `py32io_gpio_direction_input()` function failed to validate a user-supplied pin offset against the chip's declared GPIO count, opening the door to memory corruption via the GPIO character device interface. A two-line bounds check now closes the vulnerability cleanly and efficiently.

high

Buffer Overflow in RS-232 Serial Input: How a Missing Length Check Put Embedded Systems at Risk

A critical buffer overflow vulnerability was discovered in `serial.c`, where the `rs232_buffered_input` function could write more bytes than the destination buffer `rs232_ibuff` could hold — with no size limit to stop it. An attacker with access to the RS-232 serial port could exploit this to overwrite adjacent OS memory, including return addresses and critical data structures. The fix adds a simple but essential bounds check that clamps the returned byte count to the actual buffer size.