NIS+ and signed directory objects

Sun Security Coordination (secure@SUNSC.ENG.SUN.COM)
Tue, 15 Apr 1997 18:43:56 -0700

On Thu Mar 27 11:17:20 1997,

Bill Paul (wpaul@CTR.COLUMBIA.EDU) wrote:

>
> 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.

>
> -Bill

Bill's analysis is correct. nis_cachemgr does not check for signatures
resulting in the possibility of loading bogus directory objects in the
cache managed by nis_cachemgr. This is a bug that is fixed in Solaris 2.6
which is expected to be released later this year. The only workaround is
to disable nis_cachemgr on the client machines. Sun is investigating
patching this bug for Solaris 2.3, 2.4, 2.5, and 2.5.1 and will announce the
availability of the patches later through a Sun bulletin.