The NFS protocol is designed to allow systems to access files across the network on a remote system, as conveniently as if the files were on directly attached disks. Machines may be NFS servers (exporting their disks for access by other machines), NFS clients (accessing disks exported by NFS servers), or both. NFS is heavily used within LANs, but it is unsafe to allow across a firewall for a variety of reasons.
The primary problem with NFS is its weak authentication of requests. Access to a given NFS-exported filesystem is all or nothing; a given client machine is either trusted to access the filesystem, or it isn't. If the server trusts a given client machine, the server believes whatever the client tells it about who is trying to access which files. It then uses that information for authorization according to the standard UNIX file protection mechanisms (i.e., user, group, and other permissions). There are a few extra protections some NFS servers can optionally apply.
The server's trust in the client is established when the client mounts the filesystem from the server. The client contacts the server and tells the server what filesystem it wants to access. The server checks whether or not the client (based on IP address) is allowed to access that filesystem. If it is, the server gives the client a "file handle" (basically a magic set of credentials for the client), which the client uses for all further access to the filesystem.
Once the client has mounted the filesystem (and received a file handle from the server) the client sends a request to the server each time it wants to act on a file on that filesystem. The request describes the action the client wants to take and includes the file handle obtained from the server, so the server assumes that the client is authorized to request that action.
NFS's main security problems are:
The NFS server relies on IP address to authenticate client hosts, making it vulnerable to address forgery.
The NFS server relies on the client to authenticate the user, making it vulnerable to any user who has compromised a client machine.
The NFS server doesn't recheck the client authentication on every request. The server assumes that if the client uses a valid file handle, the client is authorized to access that filesystem. An attacker with a forged or captured file handle can access the filesystem just as easily as a legitimate client can.
The file handle for a given filesystem is established when the filesystem is created on the server or when it is mounted for the first time on a new server mount point or from a new disk/controller pair. Unfortunately, the method for generating file handles is fairly predictable, and an attacker can probably guess the file handle if he can guess when the filesystem was created. Most NFS servers will allow any number of bad guesses without complaining or shutting down. If the attacker can somehow guess at least the day the filesystem was created - which is especially easy if the attack is against a newly installed machine - he can probably guess the file handle without too much difficulty, by trying the range of file handles that would have been assigned to filesystems created that day.
NFS servers have no mechanism for canceling file handles; once a file handle has been issued, it's good until the server filesystem is reinitialized or mounted elsewhere (even if only temporarily; when it is remounted in its original location again, it will have a new file handle). A client which had access at one time can keep using the file handle it obtained, even if the access controls (the /etc/exports file on most UNIX NFS servers) are later changed to deny access to that client.
Under NFS, root may be treated differently from normal users. Some UNIX NFS servers always treat root the same way they treat normal users: the client's root user gets the same access that the server's root user would have. Some of them always translate the client's root user to a UID known as "nobody" that is never used as a regular user; thus, this user will only have the permissions granted to the world. This "nobody" UID may be either the highest possible UID, or a UID which translates to -1 (which might be written as -1, or as the highest possible UID plus 1). On some UNIX machines, all three of these numbers (-1, 65535, and 65536) are listed in the password file as "nobody." Most UNIX NFS servers allow you to choose whether you wish to allow root access or translate it to "nobody" via an option in the /etc/exports file. Non-UNIX servers normally treat root as if it were any other user, but because that user is unlikely to have special privileges on the server, this isn't a problem.
Translating root to "nobody" is an extremely minor security improvement. Anybody who is capable of being root on the client is capable of pretending to be any user whatsoever on the client, and can therefore see and do anything any user can do. The translation hides only those files on the server restricted to access by root itself. You will still probably want to use translation wherever you can for the minimal protection it does give you, but you should not feel that it makes it safe to export filesystems to possibly hostile clients.
Better protection for the server is available by exporting the filesystem read-only. If the filesystem is exported purely read-only (no host is allowed to write it) you can be reasonably certain the data cannot be modified via NFS. If you allow any host to write it, you're vulnerable to forgery.
NFS clients may also be in danger from NFS servers. For example, an NFS-mounted filesystem may contain setuid programs; users on the client would be able to use those programs to become root. Device entries on an NFS-mounted partition are considered to apply to the client's devices, not the server's devices. Somebody with an account on an NFS client and root permission on an NFS server, can use this to get unlimited, if inconvenient, read-write access to all data on the client.
Some NFS clients provide options to mount that can be used to disable devices and setuid/setgid on mounted filesystems. If mount is not available to users other than root, or if it always uses these options for users other than root, this will protect the client from the server. If these options are not available, even if only root can mount filesystems, you should consider mounting a filesystem to be equivalent to granting root access to the server machine.
Some vendors also support a version of NFS based on Secure RPC. Secure RPC has several problems that also apply to NFS implemented on top of it:
It is not widely supported; it is available almost exclusively on Suns.
The process of exchanging keys between machines is difficult.
It doesn't perform as well as standard RPC. (NFS is particularly performance-sensitive.)
If you have an immutable requirement to run NFS across your firewall to some other site, you should investigate either a private connection to that site or network-level encryption (described in Chapter 10). Be aware that NFS generally doesn't perform well over networks running at anything less than Ethernet speed anyway. You might want to investigate alternatives such as FTP for your particular situation or alternate network filesystems such as the Andrew File System (AFS) (see Appendix B for more information).
NFS is an RPC-based service. As mentioned in Chapter 6, it's very difficult to handle RPC-based services with a packet filtering system, because the servers normally don't use predictable port numbers. While the port numbers to be used are too unpredictable for a packet filtering system to cope with, they're not so unpredictable an attacker can't find them. (If nothing else, the attacker could try sending NFS requests to all ports to see which respond as he would expect an NFS server to respond.)
NFS is generally provided over UDP; there are TCP-based NFS servers and clients available, but they are rare and seldom used. NFS is somewhat unusual for an RPC-based service in that it normally uses a predictable port number (port 2049) - apparently for obscure reasons related to how NFS servers interact with the kernel on most UNIX systems. We wouldn't recommend depending on NFS servers to always wind up on port 2049, however. RFC 1094, the NFS protocol specification, says "The NFS protocol currently uses the UDP port number 2049. This is not an officially assigned port, so later versions of the protocol use the `Portmapping' facility of RPC."
RPC-based protocols are almost as unpleasant to proxy as they are to allow with packet filtering; they cannot be adequately handled with generic proxies. A dedicated NFS proxy server would be possible, but we do not know of one. NFS is particularly problematic for proxying, because it is data-intense, exchanging large volumes of data in situations where delay is very noticeable to the user. A host doing NFS proxying is going to need to deal with multiple connections transferring large packets at high speeds.
Don't allow NFS across your firewall.