Bugtraq mailing list archives

Re: Why you should avoid world-writable directories


From: robert () cyrus watson org (Robert Watson)
Date: Sun, 27 Dec 1998 18:22:29 -0500


On Sat, 26 Dec 1998, Bill Paul wrote:

When I tried to implement this for FreeBSD (mainly so that I could
get keyserv to work without keyenvoy), I took something of a shortcut
by having the credentials filled in by unp_internalize() in uipc_usrreq.c.
This has the side effect of requiring the caller to use sendmsg() if it
wants to send credentials to the process on the other side (which also
needs to use recvmsg() to receive them). You can use sendmsg() with either
a SOCK_DGRAM or SOCK_STREAM socket, so you end up with credentials sent
every time the caller transmits data regardless of the socket type.

This requires some extra work on the part of the caller: it must
set up the msghdr struct to use with sendmsg() and it has to pretend
to send its credentials as a control message, however the actual
credentials are filled in by the kernel regardless of what the caller
tries to send (i.e. it can try to lie about its identity, but the
kernel will blow its cover).

A properly written receiving process will always use recvmsg() to
read data from the caller and will insist that control message of type
CMSG_CREDS be present with each transmission, otherwise it will drop
the data on the floor. This means that if the caller tries to send
data using write() the receiver will ignore it since, while the data
will get through, there will be no ancillary data with it.

I patched FreeBSD this summer to allow loadable kernel modules to hook the
unp_* whtever transfer routines (currently supporting file descriptors and
the credential behavior described previously) so that arbitrary
kernel-oriented data structures could be passed when desired.  My specific
goal was to allow the passing of kernel authentication and authorization
tokens between processes so as to set up a token management daemon that
could delegate authority for useful things (like binding ports, etc).
This behavior could easily be used to extend the passing of kernel
structures in whatever direct is desired.  The most useful one, file
descriptor passing, is already present in most implementations and is
under-used by a lot of software that would benefit from it.

One interesting variation I played with was the passing of gid and uid
structures between processes in return for kerberos tickets or other
tokens.  Users started out initially un-authenticated and generally
un-authorized (no active UID or GID tokens).  When they presented
appropriate authentication material (passwords, network authentication
tickets, certificates) they could be given (via passing over a socket)
tokens authenticating or otherwise authorizing them to the kernel.  I also
added a 'reflection' form of the tokens where the kernel provided an easy
mechanism by which processes could prove their identity, membership in a
group, authorization to perform a privileged activity, etc, without
delegating that authentication or authorization.  This behavior is similar
to that which you have been describing.  My hope was this achitecture
would provide a more general framework for UNIX-like operating systems,
especially when integrating UNIX into a distributed environment.

Information on an early version of this (much of the later work I did has
not yet been released) is available at

http://www.watson.org/fbsd-hardening/tokens/

The project has also been somewhat stalled due to involvement in other
projects.:)

  Robert N Watson

robert () fledge watson org              http://www.watson.org/~robert/
PGP key fingerprint: 03 01 DD 8E 15 67 48 73  25 6D 10 FC EC 68 C1 1C

Carnegie Mellon University            http://www.cmu.edu/
TIS Labs at Network Associates, Inc.  http://www.tis.com/
SafePort Network Services             http://www.safeport.com/



Current thread: