[comp.unix.wizards] Unexpected NFS Effects

ksh@itd.dsto.oz (Ken Hayman) (06/15/89)

We have a network of Sun 3/60's which have most of their files mounted from a
3/280 server via NFS. Both the server and the clients are running SunOS 3.5,
although I believe the effect is the same under 4.x. The server is configured in
the "secure" mode, where "root" on a client is mapped to "nobody" on the server
before access is granted, and this appears to be, in the main, working as
expected (eg I can't become root on a client then write into an NFS-mounted
directory).

An interesting effect that we found though involves files with mode 711 (I
suspect the 7 isn't important, but it doesn't work if the files are 700).
Given a such a file on the NFS mounted file system (ls -lg would show, eg,

-rwx--x--x  1  user   group   10 Jun 14 10:00 file

), it has been found that if I log in a root on a client I can cp the file,
despite not owning the file (and not being part of "group").

Now I would expect that, if "root" was mapped to "nobody" on the server then I
should only have execute access to the file, and cp should give "permission
denied". My question is, is this
        a) a known bug
        b) a new bug
        c) expected behaviour?

If the answer is (c), WHY is it expected behaviour (it seems intuitively
reasonable that if I haven't got READ access I shouldn't be able to copy the
file)

Ken Hayman
+-----------------------------------------------------------------------------+
| Ken Hayman, TCS Group, DSTO Salisbury, S.Aust  ACSnet:   ksh@itd.dsto.oz    |
| Phone:      +61 8 259 6340                     Internet: ksh@itd.dsto.oz.au |
+-----------------------------------------------------------------------------+

jik@athena.mit.edu (Jonathan I. Kamens) (06/15/89)

In article <403@fang.dsto.oz> ksh@itd.dsto.oz (Ken Hayman) writes:
>An interesting effect that we found though involves files with mode 711 (I
>suspect the 7 isn't important, but it doesn't work if the files are 700).
>Given a such a file on the NFS mounted file system (ls -lg would show, eg,
>
>-rwx--x--x  1  user   group   10 Jun 14 10:00 file
>
>), it has been found that if I log in a root on a client I can cp the file,
>despite not owning the file (and not being part of "group").
>
>Now I would expect that, if "root" was mapped to "nobody" on the server then I
>should only have execute access to the file, and cp should give "permission
>denied". My question is, is this
>        a) a known bug
>        b) a new bug
>        c) expected behaviour?

It is known behavior, but I am not quite sure it should be classified
as a "bug."

Let's say that you make a file on your local disk mode 711, owned by
root with group operators (or whatever).  This means that the world at
large is allowed to execute the binary, but not to read its contents.
To the kernel, this means that if a request is made to execute this
program, it will be loaded into memory and executed, but if a request
is made to read the contents of the file, it will be denied (unless
the user making the request is root, of course).

Now, take this same file and put it on a remote, secure NFS filesystem.
The kernel gets a request to execute this file, but since the file is
not on a local disk over which the kernel has direct access, it has to
*read* the file using NFS before it can execute it.

Now, NFS can draw no distinction between a root user making a read
request and a kernel, running as root (well, actually, the kernel is
below the level of root, but you get the idea :-), making read
requests, and there is no difference in NFS between a "read for user
viewing" and "read for execution" request.  Therefore, in order for a
kernel to be able to execute a program on an NFS filesystem for which
the user has only execute permissions, the kernel has to be able to
*read* the file using an NFS request.

Because of this necessity, the superuser has the ability to read any
file that has any execute bits set; therefore, you can su to root on
the client and read the file that is mode 711 on the NFS server.

I hope I explained that clearly -- *I* hardly understand that
explanation, and I wrote it :-)

Jonathan Kamens			              USnail:
MIT Project Athena				432 S. Rose Blvd.
jik@Athena.MIT.EDU				Akron, OH  44320
Office: 617-253-4261			      Home: 216-869-6432

chris@softway.oz (Chris Maltby) (06/19/89)

Jonathan I. Kamens writes:
: Now, NFS can draw no distinction between a root user making a read
: request and a kernel [...] making read requests, and there is no
: difference in NFS between a "read for user viewing" and "read for
: execution" request.

So that's how it is, I'm sure. The question now is "Why?". I can't think
of any reason why you couldn't pass a "read for execution" request distinct
from a "read as data" request. I guess someone crocked the design... (:-)
-- 
Chris Maltby - Softway Pty Ltd	(chris@softway.sw.oz)

PHONE:	+61-2-698-2322		UUCP:		uunet!softway.sw.oz.au!chris
FAX:	+61-2-699-9174		INTERNET:	chris@softway.sw.oz.au

mwp@munnari (Michael Paddon) (06/21/89)

From article <1703@softway.oz>, by chris@softway.oz (Chris Maltby):
> 
> So that's how it is, I'm sure. The question now is "Why?". I can't think
> of any reason why you couldn't pass a "read for execution" request distinct
> from a "read as data" request. I guess someone crocked the design... (:-)

How would this increase security? All I can see is more complexity in
the protocol for absolutely no return.

All root has to do is construct a request that says "read this
file for execution". Sure, it's a little harder, but we all know how
useful security via obscurity is (even if you don't have NFS source).

The other point to remember is that NFS is a general protocol (not Unix
specific). It just requires that there is a trusted context which does
stuff like executing files. In Unix, that context is the kernel; for
historical reasons the kernel and root are trusted equally from the
security viewpoint.

The way to provide security is to ensure that the root account *and* the
kernel can be trusted. A third party authentication scheme fits the bill
nicely.

-------------------------------------------------------------
|                  | email: mwp@munnari.oz.au               |
|                  | voice: (03) 344 4246                   |
|  Michael Paddon  | snail: Department of Computer Science, |
|                  |        The University of Melbourne,    |
|                  |        Parkville 3052, Australia       |
-------------------------------------------------------------

jik@athena.mit.edu (Jonathan I. Kamens) (06/28/89)

In article <1703@softway.oz> chris@softway.oz (Chris Maltby) writes:
>So that's how it is, I'm sure. The question now is "Why?". I can't think
>of any reason why you couldn't pass a "read for execution" request distinct
>from a "read as data" request. I guess someone crocked the design... (:-)

RFE = Read For Execution
RAD = Read As Data

First of all, a malicious user can lie and send an RFE and get the
binary image with little effort (it *really* isn't that hard to spoof
NFS packets :-).  Second, the distinction between RFE and RAD in an
ideal situation would be that only a kernel process would be allowed
to make an RFE, and that distinction cannot be enforced on the server
side, only on the client side.  Therefore, an RFE request would still
require that root on the client be trusted.  That's what's being
assumed under the present system, since any executable is readable by
root, so you don't gain anything by separating the operations.

Second, once you've actually got the binary image running on your
machine, I can think of any number of ways to get the actual contents
of the program image.  The first one that comes to mind is sending it
a signal that causes it to dump core and then undumping the core file
to get a binary.  How many programs do you know that trap *all*
signals and can prevent core dumps in all cases?

Jonathan Kamens			              USnail:
MIT Project Athena				432 S. Rose Blvd.
jik@Athena.MIT.EDU				Akron, OH  44320
Office: 617-253-4261			      Home: 216-869-6432

guy@auspex.auspex.com (Guy Harris) (06/29/89)

>So that's how it is, I'm sure. The question now is "Why?". I can't think
>of any reason why you couldn't pass a "read for execution" request distinct
>from a "read as data" request.

Even if you could, it wouldn't provide real security - just write
user-level NFS client code (not too painful) that "reads" a file by
using "read for execution" requests.

In other words, don't assume packets coming into your server are being
generated by a "trusted" source, unless you have some way of verifying
that.  I know of another remote file system that, as far as I can tell,
trusts requests to some degree, and would let me open a file for
reading and then make "write" requests to it, simply by generating the
messages myself rather than going through the kernel code....

wesommer@athena.mit.edu (Bill Sommerfeld) (06/30/89)

In article <1602@munnari.oz.au> mwp@munnari (Michael Paddon) writes:

   The other point to remember is that NFS is a general protocol (not Unix
   specific). 

I find this hard to believe.  The documentation pays lip service to
this goal, but fall badly short of it in a number of places.  (That
line seems to be used as an excuse for not providing full UNIX
semantics).

*) The set of attributes associated with files corresponds exactly
(1:1) with the attributes used in UNIX, and there's no way to extend
the attributes passed around (that's not UNIX-specific?).

*) The protocol attempts to hide the fact that '/' is the path component
separator, except that '/' are passed "bare" in symlinks.

*) Access control must be inferred on the client from the
(UNIX-specific) file attributes provided by the server.  The server
gets to trump the client's decision, of course, but at that point it
may be too late.

There are others..

					- Bill
--