[61] in linux-security and linux-alert archive
Safe NFS outline
daemon@ATHENA.MIT.EDU (Thomas Koenig)
Wed Mar 8 11:42:38 1995
To: linux-security@tarsier.cv.nrao.edu (linux-security)
Date: Wed, 8 Mar 1995 15:49:58 +0100 (MET)
From: Thomas.Koenig@ciw.uni-karlsruhe.de (Thomas Koenig)
Reply-To: linux-security@tarsier.cv.nrao.edu
Here's an outline for an nfsd I dreamt up together with Mike pall
(pall@rz.uni-karlsruhe.de) some time ago. It's compatible with
current servers (or so I think) and shouldn't be too hard
to implement.
Comments, anybody?
Thomas
The current state of NFS authentication is fairly bad. Once a client
has obtained a valid NFS handle by whatever means (guessing, net
spoofing, whatever) it can work its way from there. Because a NFS
server is stateless, it's not supposed to keep around records of
who mounts what.
Current clients use AUTH_UNIX for their credentials (there are actually
some NFS implementations around with trust the hostname in there... I
have no idea why they should do that) with a null verifier. Trying to
get that fixed is useless.
However, there is enough room in the file handle itself for verification
data, which can be done with a secure hash like MD5.
The scheme I dreamt up with Mike Pall is the following:
A mount request comes in for client foo, which wants to mount
directory /bar. The mount daemon checks that this is indeed permitted
and generates a record (called 'clientpoint') for the mount request.
This contains the following information:
- Major and minor device number of the mountpoint
- Inode number of the mountpoint
- IP address of the client
- A secret key (64 bits or so) generated from pseudorandom data, such
as timer resolution at the microsecond level, networking statistics,
and whatever. This changes from mount request to mount request.
- Flags, such as readonly status, wether the entry is actually valid,
and the like.
This clientpoint entry is indexed, and should be stored on disk
(probably mmaped() by both mountd and nfsd).
The mountd then generates a NFS file handle with the following information:
- Major and minor inode numbers (4 bytes each)
- Inode number of the mountpoint (4 bytes)
- Clientindex number (4 bytes)
- Autentication data, which is generated by a MD5 hash over all the
clientpoint data plus the data in the file handle. This includes
the secret key.
If a NFS request comes in to the nfsd, the first thing it does is to get
is the clientpoint for the request. If it doesn't, probably somebody is
playing guessing games :-)
Assuming it exists, the next thing to compare would be wether
the IP address of the sender and the one for the clientpoint.
If it doesn't, chances are somebody is trying to feed a NFS handle
to us which is valid for another machine (network spoofing?).
After this, a MD5 checksum (over the same clientpoint entry and the file
handle the client just sent us). If these don't match, it might be that
a client, who may be able to mount some files legitimately is trying to
get a file handle for my root filesystem.
Before doing the actual operation, the kernel nfsd would have
set the fsuid and done the (kernel - equivalent) of a chroot()
call. No way to break out, then ;-)
What else? Well, the number of clientpoints has to be kept fairly
low. If a client wants to remount the same filesystem for which it
hadn't done an unmount, chances are it crashed in the meantime and
doesn't remember about the old handles, anyway. Other than that,
I see no legitimate reason for a single client machine to mount
the same directory more than, let's say, two times (to be made
an option). It will make a nice entry in the BUGS section, though ;-)
When /etc/exports is read anew, mountd should amble along the
clientpoints file and throw out anything that's no longer permitted.
Performance: I tried MD5 on my 486/33 and got about 200000
rounds/second. This would be good enough, I think.
Keeping state around: Well, some is inevitable, if you want an
approximation of a secure NFS. You have to keep track of who's
mounting what.