Bugtraq mailing list archives

NIS+ and signed directory objects (not!)


From: wpaul () CTR COLUMBIA EDU (Bill Paul)
Date: Thu, 27 Mar 1997 11:33:07 -0500


Okay, I have some questions about security on NIS+ clients. It seems
to me there's a gaping hole, but I could be wrong.

NIS+ clients run a daemon called nis_cachemgr which is designed to
cache directory 'objects' returned from NIS+ servers. The object is
really an XDR encoded directory_obj structure (as defined in
<rpcsvc/nis_object.x>). The tricky part about nis_cachemgr is that
any local process on the system is allowed to send it requests to
cache objects; nis_cachemgr is basically just an RPC server, with
a protocol defined in <rpcsvc/nis_cache.x>. Since NIS+ directory
lookups are performed by library code in libnsl, they might be made
by anyone on the system; hence nis_cachemgr must be prepared to
accept updates from privileged and unprivileged users alike.

The cache (/var/nis/NIS_SHARED_DIRCACHE) is later accessed by other
processes: if, say, user 'foo' does an 'niscat passwd.org_dir,' this
will cause the org_dir object to be saved in /var/nis/NIS_SHARED_DIRCACHE.
Subsequently, user 'bar' may issue the same command, but rather than
asking the remote server to do a directory lookup all over again,
the client NIS+ library reads the org_dir object from the cache.

An obvious question is: what happens if a malicious user decides to
write his own client program to talk to nis_cachemgr and instructs it
to load the cache with bogus objects? How can nis_cachemgr tell if
the request is legitimate or if the user is just trying to be a wiseass?

The answer is supposed to be the 'signature' contained in the fd_result
structure returned by the NIS+ server (rpc.nisd). The server is supposed
to compute an MD5 digest of the encoded directory object and encrypt it
(with ecb_crypt()) using a Secure RPC conversation key. This conversation
key consists of the server's secret key and the requester's public key.
(You can get it from the keyserv daemon with the key_get_conv() function.)

Since nis_cachemgr runs as root, its principal name is the same as
the 'requester' listed in the finddirectory request, hence it will be
able to compute its own signature and compare it to the one generated
by the server (using its secret key and the server's public key).
Since only the server knows its RPC secret key, it should be impossible
for a user to forge a directory object because it can't create a proper
signature.

But here's the problem: from what I can tell, rpc.nisd never signs its
directory objects and nis_cachemgr never checks for them. I've run
several tests with Solaris 2.5.1 on a couple of different machines.
I've set up a dummy root server and a single dummy client, with all
the right credentials. Authentication of the client works correctly
and the service seems to function properly. However, when I use a
test program to call the NIS_FINDDIRECTORY procedure on rpc.nisd,
the server sends back an object without a signature. I tried several
different variations (using AUTH_DES authentication, using AUTH_SYS
authentication, using no authentication, running the program on the
server host itself) but I could never get rpc.nisd to supply a signed
directory object.

At first I was convinced that I was omitting some magic in my test
program since I could tell that nis_cachemgr was adding directory objects
to the client's cache. The nis_cachemgr man page states that it will
always attempt to authenticate the signature unless you start it with
the -i flag (to activate insecure mode). I did not start nis_cachemgr
with the -i flag, so it should have been checking for signatures and
if rpc.nisd wasn't sending them, it would never have updated the cache.

Finally, after simplifying the test program as much as I could and
still not getting any results, I started to think that maybe the problem
was with rpc.nisd after all. Thanks go gdb, I finally learned what was
going on: the insecureMode flag in nis_cachemgr starts off initialized to
0 but is forced to 1 later in the program even though nis_cachemgr was
_NOT_ started with -i. In other words, nis_cachemgr doesn't really check
for signatures at all, which bore out my hunch that rpc.nisd was never
sending them. As a further test, I even toggled the insecureMode flag
back off with gdb and let nis_cachemgr continue running; now, as I
expected, it would no longer add any directory objects to the cache since
it couldn't verify the signatures.

I haven't tried running gdb on rpc.nisd since I'm confused enough
as it is.

So here's what I'm wondering: can anyone think of a reason why the
signature generation and checking has been lobotomized? And for that
matter, does this impact security on NIS+ clients as much as I think it
does? It occured to me that maybe there might be some special encryption
kit that has to be installed for this stuff to work right, but that
doesn't make sense since Secure RPC already works with the stock Solaris
distribution, and that's all that's really needed for generating
signatures.

I'm also wondering if maybe there's something fishy going on between
nis_cachemgr and nscd (the name service cache daemon) that somehow
negates the risk of not having signatures. I can't see how though.

-Bill

--
=============================================================================
-Bill Paul            (212) 854-6020 | System Manager, Master of Unix-Fu
Work:         wpaul () ctr columbia edu | Center for Telecommunications Research
Home:  wpaul () skynet ctr columbia edu | Columbia University, New York City
=============================================================================
  "Now, that's "Open" as used in the sentence "Open your wallet", right?"
=============================================================================



Current thread: