15.4 Improving NFS Security

There are many techniques that you can use to improve overall NFS security:

  • Limit the use of NFS by limiting the machines to which filesystems are exported, and limit the number of filesystems that each client mounts.

  • Export filesystems read-only if possible.

  • Use root ownership of exported files and directories.

  • Remove group write permissions from exported files and directories.

  • Do not export the server's executables.

  • Do not export home directories.

  • Do not allow users to log into the NFS server.

  • Use the fsirand program, as described later in this chapter.

  • Set the portmon variable so that NFS requests that are not received from privileged ports will be ignored.

  • Use showmount -e to verify that you are exporting only the filesystem you wish to export to the hosts specified, and with the correct flags.

  • Use Secure NFS.

These techniques are described in the following sections.

15.4.1 Limit Exported and Mounted Filesystems

The best way to limit the danger of NFS is by having each computer export and/or mount only the particular filesystems that are needed.

If a filesystem does not need to be exported, do not export it. If it must be exported, export it to as few machines as possible by judiciously using restrictions in the exports list. If you have a sizeable number of machines to export to, and if such lists are tedious to maintain, consider careful use of the netgroups mechanism, if you have it. Do not export a filesystem to any computer unless you have to. If possible, export filesystems read-only.

If you only need to export part of a filesystem, then export only that part. Do not export an entire filesystem if you need access to only a particular directory.

Likewise, your clients should mount only the NFS servers that are needed. Don't simply have every client in your organization mount every NFS server. Limiting the number of mounted NFS filesystems will improve overall security, and will improve performance and reliability as well.

The above advice may seem simple, but it is advice that is rarely followed. Many organizations have configured their computers so that every server exports all of its filesystems so that every client mounts every exported filesystem. And the configuration gets worse: some computers on the Internet today make filesystems available without restriction to every other computer on the Internet. Carelessness or ignorance is usually to blame: a system administrator faced with the need to allow access to a directory believes that the easiest (or only) way to provide the access is to simply enable file sharing for everybody. One of us once watched a student in a lab in the Netherlands mount filesystems from more than 25 U.S. universities and corporations on his workstation?most with read/write access![14]

[14] He could have mounted many more, but it was time to leave for dinner.

Export Can Be Forever

Some versions of NFS enforce the exports file only during mount, which means that clients that mount filesystems on a server will continue to have access to those filesystems until the clients unmount the server's filesystems or until the filesystems are rebooted. Even if the client is removed from the server's exports file and the server is rebooted, the client will continue to have access and can continue to use a filesystem after unmounting it, unless the directory is no longer exported at all, or unless fsirand is run on the exported filesystem to change the generation count of each inode.

Distinguishing a file handle that is guessed from one that is returned to the client by the mount daemon is impossible. Thus, on systems where the exports are examined only upon mounting, any file on the NFS server can be accessed by an adversary who has the ability and determination to search for valid file handles.

Many modern NFS servers check exports on each client access, rather than only on mount. The example explained

In the example we presented earlier in this chapter, Example 15-1an /etc/dfs/dfstab file with some problems," a system administrator made three dangerous mistakes. On the third line, the administrator exported the directory /tftpboot. This directory is exported to any computer on the network that wishes to mount it; if the computer is on the Internet, then any other computer on the Internet has access to this server's /tftpboot directory.

What's the harm? First of all, users of the /tftpboot directory may not be aware that files that they place in it can be so widely accessed. Another problem arises if the directory can be written: in this case, there is a possibility that the storage space will be hijacked by software pirates and used as a software pirate "warez" repository. Perhaps worse, the software on that partition can be replaced with hacked versions that may not perform as the real owners expect! (In this case, /tftpboot is probably used for providing bootstrap code to machines on the network. By modifying this code, a resourceful attacker could force arbitrary computers to run password sniffers, erase their hard drives, or do other unwanted things.)

The last two lines of the sample configuration file have a similar problem: they export the directories /usr/lib/X11/ncd and /usr/openwin freely over the network. Although the directories are exported read-only, there is still a chance that a software pirate could use the exported filesystems to obtain copies of copyrighted software. This scenario could create a legal liability for the site running the NFS server.

You can make your server more secure by exporting filesystems only to the particular computers that need to use those filesystems. Don't export filesystems that don't have to be exported. And don't export filesystems to the entire Internet?otherwise, you will only be asking for trouble.

Here is a revised dfstab file that is properly configured:

#       Place share(1M) commands here for automatic execution
#       upon entering init state 3.
#       This configuration is more secure.
share -F nfs -o rw=red:blue:green /cpg
share -F nfs -o rw=clients -d "spool" /var/spool
share -F nfs -o ro=clients /tftpboot
share -F nfs -o ro=clients /usr/lib/X11/ncd
share -F nfs -o ro=clients /usr/openwin

Be aware that the options to export commands and configuration files have different semantics under SVR4 and earlier, BSD-like systems (including SunOS). Under earlier BSD-like systems, the -ro option does not take hostnames as parameters, and there is an -access option to limit access. If you specified an export list under SunOS as in the above example:

exportfs -i -o rw=clients /var/spool

then the directory is exported read/write to the members of the clients netgroup, but it is also exported read-only to everyone else on the network! You must also specify the -access option with the -rw option to limit the scope of the export. Thus, to prevent other machines from reading exported files, you must use the following command:

exportfs -i -o rw=clients,access=clients /var/spool

Under SVR4, both the -rw and -ro options can take a host list to restrict the export of the files. The directory is exported only to the hosts named in the union of the two lists. There is no -access option in SVR4.

15.4.2 Export Read-Only

Many filesystems contain information that is only read?never (or rarely) written. These filesystems can be exported read-only. Exporting the filesystems read-only adds to both security and reliability: it prevents the filesystems from being modified by NFS clients, limiting the damage that can be done by attackers, ignorant users, and buggy software.

Many kinds of filesystems are candidates for read-only export:

  • Filesystems containing applications

  • Organizational reference matter, such as policies and documents

  • Web server document roots

If you have programs or other files that must be exported read-write, you can improve your system's overall performance, reliability, and security by placing these items on their own filesystem that is separately exported.

To export a filesystem read-only, specify the ro=clients option in either your exports file or your dfstab file (depending on which version of Unix you are using). In the following example, the /LocalLibrary directory is exported read-only:

share -F nfs -o ro=clients /LocalLibrary

15.4.3 Use Root Ownership

Because the NFS server maps root to nobody, you can protect files and directories on your server by setting their owner to root and their protection modes to 755 (in the case of programs and directories) or 644 (in the case of datafiles). This setup will prevent the contents of the files from being modified by a client machine.

If you have information on an NFS server that should not be accessible to NFS clients, you can use the file protection mode 700 (in the case of programs and directories) or 600 (in the case of datafiles). However, a better strategy is to avoid placing the files on the NFS server in the first place.

Remember, this system protects only files on the server that are owned by root. Also, this technique does not work if you have patched your kernel to set the value of nobody to 0, or if you export the filesystems to a particular host with the -root= option.

Protecting an executable file to be execute-only will not work as you expect in an NFS environment. Because you must read a file into memory before it can be executed, any file marked executable can also be read from a server using NFS commands (although it may not be possible to do so using standard calls through a client). The server has no way of knowing whether the requests to be read are a prelude to execution or not. Thus, putting execute-only files on an exported partition may allow them to be examined or copied from a client machine.

15.4.4 Remove Group-Write Permission for Files and Directories

If you are using standard AUTH_UNIX authentication with NFS, then users can effectively place themselves in any group. Thus, to protect files and directories that are owned by root, they must not be group-writable.

15.4.5 Do Not Export Server Executables

If your server is running the same operating system on the same CPU architecture as your client computers, then you might be tempted to have the server export its own executables (such as the programs stored in /bin, /usr/bin, etc.) for use by the clients. Don't do so without careful thought about the consequences.

At first, exporting a server's own executables seems like a good way to save disk space: this way, you need to have only one copy of each program (which is then shared between the clients and the servers) rather than two copies.

But exporting your server's executables poses several security problems:

  • It allows an attacker to easily determine which version of each executable your server is running, which enables the attacker to probe for weak spots with greater ease.

  • If there is an error in your system's configuration, you may be exporting the binaries on a writable filesystem. An attacker could then modify the server's own binaries, and possibly break in (or at least cause you serious problems).

You can minimize the need for exporting server binaries by using the dataless client configuration that is available on some versions of Unix. In this case, "dataless" means that each client computer maintains a complete copy of all of its executable files, but stores all of its data that is subject to change on a central server.

If you simply must export the server's binaries, then export the filesystem read-only.

15.4.6 Do Not Export Home Directories

If you export a filesystem that has users' home directories on it and you do not use Secure RPC, then all other clients mounting that directory, as well as the server itself, can be placed at risk.

If you generally export a filesystem that contains users' home directories, then there is a risk that an attacker could alter the information stored on the NFS server. This is normally a serious risk in itself. However, if the partition being exported includes users' home directories, then one of the things that an attacker can do is create files in the users' home directories.

A simple attack is for an attacker to create a .rhosts file or an entry in .ssh/authorized_keys in a user's home directory that specifically allows access for the attacker. Having created this file, the attacker can log onto the server and proceed to look for additional security holes. Perhaps the greatest danger in this attack is that it can be aimed against system accounts (such as daemon and bin) as easily as accounts used by human users. An attacker can also access email, change the startup files, and otherwise read or alter sensitive files?including SSH keys and configuration, and X Window System key files.

Likewise, you should avoid exporting filesystems that contain world-writable directories (e.g., /tmp, /usr/tmp, /usr/spool/uucppublic).

15.4.7 Do Not Allow Users to Log into the Server

NFS and direct logins are two fundamentally different ways to use a computer. If you allow users to log into a server, the user can use that access to probe for weaknesses that can be exploited from NFS, and vice versa.

15.4.8 Use fsirand

One of the security problems with NFS is that the file handles used to reference a file consist solely of a filesystem ID, an inode number, and a generation count. Guessing valid file handles is easy in most circumstances. Filesystem IDs are normally small numbers; the root directory on the standard Unix filesystem has the inode number 2, /lost+found has the inode number 3, and so on. The only difficulty in guessing a file handle is the generation count. For many important inodes, including the root inode, we would expect the generation count to be very small?we don't normally delete a filesystem's root entry!

The fsirand program increases the difficulty of guessing a valid file handle by randomizing the generation number of every inode on a filesystem. The effect is transparent to the user?files and directories are still fetched as appropriate when a reference is made?but someone on the outside is unable to guess file handles for files and directories anymore.

You can run fsirand on the root directory while in single-user mode or on any unmounted filesystem that will fsck without error.

For example, to run fsirand on your /dev/sd1a partition, type the following:

# umount /dev/sd1a                          Unmount the filesystem
# fsirand /dev/sd1a                         Run fsirand

You might benefit from running fsirand once a month on your exported partitions. Some people run it automatically every time the system boots, but this has the disadvantage of making all legitimate file handles stale, too. Consider your environment before taking such a drastic step.

The fsirand program is not available on all versions of Unix. In particular, it is not available under Linux.

Older versions of Sun's fsirand contained buggy code that made the "random" values quite predictable. Be sure you have the latest version of fsirand from your vendor. Most newer versions of the newfs command automatically run fsirand, but not all do. The functionality of fsirand is incorporated into the Solaris 2.5 mkfs command.

15.4.9 Set the portmon Variable

Normally, NFS servers respond to requests that are transmitted from any UDP port. However, because NFS requests are supposed to come from kernels of other computers, and not from users who are running user-level programs on other computers, a simple way to improve the security of NFS servers is to program them to reject NFS requests that do not come from privileged ports. On many NFS servers, the way that this restriction is established is by setting the kernel variable nfs_portmon to 1. It's important to do this if you want even a minimal amount of NFS security.[15]

[15] The value of 1 is not the default because some vendors' NFS implementations don't send requests from ports <1024. If you set portmon, those vendors' machines will not be able to be NFS clients from this NFS server.

If you are using SunOS, you can set the nfs_portmon variable to 1 using the adb debugger:[16]

[16] If you rebuild the kernel, these modifications will be lost. You may want to consider adding them to /etc/rc/local. (A version of this command is in /etc/rc/* on some systems.)

# adb -k -w /vmunix /dev/mem                           Changes kernel disk file
nfs_portmon/W1                                         Changes running kernel
_nfs_portmon: _nfs_portmon: 0                           The default setting
?W1                                                    Change to 1
$q                                                     Write out the result

If you are using Solaris 2.1-2.4, you can set the portmon variable by inserting this line into your /etc/system file:

set nfs:nfs_portmon = 1

If you are using Solaris 2.5 and above, you can set the variable by inserting this line into your /etc/system file:

set nfssrv:nfs_portmon = 1

On Linux systems, setting the secure option for an exported directory in /etc/exports performs the same function as nfs_portmon.

Unfortunately, restricting NFS requests to those transmitted from a privileged client port is not as useful a defense against an attacker as it may seem. If you export to any machine within your organization (or network), an attacker who is root on another Unix machine can generate traffic from a privileged port. Worse, an internal attacker may be running an operating system that has no concept of privileged ports?such as most "client" versions of Windows. To be truly effective, the restriction on client ports must be combined with strict controls on which clients can access the server.

15.4.10 Use showmount -e

The showmount -e command (mentioned earlier in this chapter) lists the host's export lists?that is, the directories and hosts that can be mounted. The showmount command allows an optional argument, host. When this argument is provided, the showmount command can be used to remotely inspect another computer's export list. The command is useful for finding NFS servers that are configured in an unsecure fashion. For example:

/usr/etc/showmount -e deadly.org
export list for deadly.org: /bigusers (everyone) /tmp2 (everyone) / (everyone) /usr (everyone) /var (everyone) /usr/public (everyone) /usr/public/pub (everyone) %

In this case, the computer deadly.org appears to be exporting its /bigusers, /tmp2, /, /usr, /var, /usr/public, and /usr/public/pub directories to every other computer on the Internet.

Fortunately, things aren't as bad as they seem at deadly.org. That's because they are using Secure NFS. Here's what happens when you try to mount the filesystem:

# mount deadly.org:/ /nfs/tmp
nfs: bad MNT RPC: RPC: Authentication error; why = Client credential too weak

15.4.11 Use Secure NFS

The biggest security problem with NFS, as it is normally configured, is that it uses Sun's AUTH_UNIX RPC authentication system. With AUTH_UNIX, a user simply provides his UID and a list of GIDs with every request. The NFS server trusts that the user is who he claims to be.

In a friendly environment, AUTH_UNIX authentication presents no problems because requests sent out by the NFS client always have the same UID and GIDs as the person who has logged in and is using the workstation. However, if the workstation user has root access, that person can use the root access to become any other user, with that other user's corresponding rights and privileges on the RPC server. A second problem with AUTH_UNIX is that user-written programs can have their AUTH_UNIX UID and GIDs set to any value.[17] When reserved port checking is enabled, AUTH_UNIX offers roughly the same level of security as the rsh/rlogin trusted-host facility.

[17] We have seen several "NFS shells" that allow a user to make such accesses in a largely automated way.

Secure NFS overcomes these problems by using AUTH_DES RPC authentication instead of AUTH_UNIX. With Secure NFS, users must be able to decrypt a special key stored on the NIS or NIS+ server before the NFS filesystem will allow the user to access his files.

To specify Secure NFS, you must specify the secure option both on the NFS server (in the exports file or the dfstab) and on the client (in the /etc/fstab or /etc/vfstab file).

Secure NFS requires Secure RPC to function, and therefore may not be available on all versions of Unix. If you are in doubt about your system, check your documentation to see if your NFS mount command supports the secure option. Also note that Secure RPC may not be available on non-Unix implementations of NFS.

Here is an example of using Secure NFS. Suppose that a server has a filesystem /Users that it will export using Secure NFS. The server's /etc/dfs/dfstab file might contain the following line:

share -F nfs -o secure,rw=clients /Users

Meanwhile, the clients /etc/vfstab file would have a matching line:

#device        device         mount       FS     fsck    mount    mount
#to mount      to fsck        pont        type   pass    at boot  options
server:/Users  -              /Users      nfs    -       yes      secure

    Part VI: Appendixes