Bugtraq mailing list archives

Re: Serious security flaw in rpc.mountd on several operating


From: lm () CS RMIT EDU AU (Luke Mewburn)
Date: Thu, 28 Aug 1997 23:55:19 +1000


Theo de Raadt writes:
I'm not sure exactly what systems this vulnerability affects, but clearly
it is a serious problem.

Since then, It has been confirmed that this hole is present on at least
some distributions/versions of Linux, Ultrix, NetBSD, OpenBSD, SunOS,
Solaris, and probably many many more.

This was solved well before 2.1 shipped.  The problem did exist in
2.0, but that's about a year old now, and has been replaced with 2.1.

Here's the log entry:

----
symbolic names:
        OPENBSD_2_1: 1.16.0.2
        OPENBSD_2_0: 1.11.0.2
        ...
revision 1.12
date: 1996/12/05 23:14:27;  author: millert;  state: Exp;  lines: +14 -9
Stop info gathering attack pointed out by Alan Cox <alan () cymru net>
Only return ENOENT if the dir trying to be mounted is really exported
to the client.  Return EACCESS if not exported.
----

Now, if I remember, Alan had posted the information about this to
BUGTRAQ, thus prompting us to fix it (there is a small chance that the
problem report actually came to us via David Holland, though).

Theo,
    I've examined your fix to this, and I believe that it may rely
upon a variable being set to a valid file system ID (fsb.f_fsid)
which won't be set to a known value if the directory requested doesn't
exist. In the random chance that fsb.f_fsid is set to a valid fsid
(because of the unknown state of uninitialised automatic variables)
then an unprivileged client will receive ENOENT instead of EACCES.

In general, as mountd doesn't know which export list to apply to a
non-existant directory, it's not possible for it to determine whether
the client is permitted or not. Therefore, it's not really feasible
to differentiate between ENOENT for "valid" clients and EACCES for
"invalid" clients.

Returning EACCES for non-existant directories as well as for lack of
sufficient permissions results in far simpler code, as opposed to a
more complicated solution, which would return EACCES except if the
requested non-existant directory would be part of an export list
that the client does have permissions for.

A pseudocode outline of the relevant code section in OpenBSD follows:
(see ftp://ftp3.usa.openbsd.org/pub/OpenBSD/src/sbin/mountd/mountd.c,
 mntsvc() function)

-->
        struct stat        stb;
        struct statfs      fsb;
        struct exportlist *ep;
        long bad = 0;

        if (stat(dirpath, &stb) < 0 ||
            (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) ||
            statfs(dirpath, &fsb) < 0) {
                bad = ENOENT;
        }
        ep = ex_search(&fsb.f_fsid);
                        /* lm: note that if the earlier stat() fails,
                           (and therefore bad=ENOENT), fsb will have
                           unknown contents because the call to statfs()
                           won't be made. Usually, however, this search
                           will fail, but there is a chance that the
                           random contents of the uninitialised fsb
                           will result in a +ve match */
        if (ep && (chk_host(ep->ex_defdir, ...) || (....))) {
                if (bad) {
                        /* lm: it's possible to get here because of
                           the conditions described above */
                        svc_sendreply(..., &bad, );     /* ENOENT */
                        return;
                }
                /* ...
                 * mount ok
                 * ...
                 */
        } else
                bad = EACCES;
        if (bad) {
                svc_sendreply(..., &bad, );     /* bad = EACCES */
                return;
        }
<--

Sure, this is probably being a bit too paranoid, but depending on the
value of an uninitialised variable probably isn't the best solution...

I hope that I haven't misinterpreted your code and caused undue alarm.

Luke.

PS:  bugtraq is a wonderful service - thanks from another (usually)
silent reader.

--
Luke Mewburn <lm () cs rmit edu au>
UNIX Technical Support, Department of Computer Science, RMIT.
Developer, NetBSD Foundation <lukem () netbsd org>



Current thread: