httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From (Robert S. Thau)
Subject Re: Authentication
Date Tue, 04 Jun 1996 18:48:05 GMT

I believe this suggestion is what Jason meant earlier by "walking the
process tree".  The problem is finding a secure way to do that.  In
particular, the only even vaguely portable way I'm aware of for getting
at the process table is 'ps', and even with it, the details (options
required to get ppid, and output formats) vary from system to system.
In what follows, I'm assuming use of 'ps' --- if anyone has a better
idea, my apologies, but I haven't seen one yet.

I obviously haven't got a complete catalog of possible attacks on such
a scheme, but here are some incomplete jottings on possibilities:

1) Tricking the wrapper into running a bogus 'ps'.
   To prevent this, assuming a system which hasn't been compromised already,
   I *think* we just need to refer to the 'ps' binary by an absolute pathname.
   However, I could be missing something --- and NB that the *location* of
   the 'ps' binary is then yet another non-portable detail which we'd have
   to take care of somehow.

2) Tricking the genuine 'ps' into producing bogus output.  Here's
   where things start to get interesting.  On systems where 'ps' is
   *not* setuid (Linux systems using /proc come to mind), attacks
   based on trojan-horse shared libraries are probably the likeliest
   approach.  However, there may be some stunt one can pull on other
   systems, involving, say, putting a hard newline into argv[0] of an
   auxiliary process, which could potentially allow attackers to
   insert lines of their own choice into 'ps' output.
3) A third possible approach is to hack the process structure itself ---
   just because you've got an ancestor which shows up on 'ps' as httpd,
   and is running as root, doesn't *necessarily* mean that that thing is
   a real web server process.  Doing an

      execl ("some suid program", "httpd", "nice", "looking", "args"...)

   and executing a shell escape from the suid program (if it has any)
   would be the general sort of thing that I'm thinking of.

4) Depending on how the check is performed, you might be able to achieve
   the same results as in (3) even with a genuine server.  The trick
   would be to have a trojan-horse CGI script rewrite its argv[0] to
   say "httpd", and then spawn off the wrapper, with bogus args.  Once
   the wrapper starts running, it walks back up the process tree, and
   finds nothing but "httpd" processes, the common ancestor of which
   (admittedly a generation farther removed than one might expect) is
   in fact a *genuine* httpd process owned by root.

Honestly, approaches based on cryptography and shared secrets strike
me as a better way to fly, if only because a lot more people have
tried for a lot longer to poke holes in them, and you can find books
saying what to expect.  Once the RSA and Diffie-Hellman patents run
out, it *will* work to use digital signatures (though you'd want the
signed text to include the arguments and a per-exec() nonce to avoid
replay attacks).  In the meantime, the biggest problems with a shared
secret approach, it seems to me are:

  *) Generating 32 bits of genuinely random data to use as a shared
     secret (not easy on a Unix box, as Netscape found out the hard way).

  *) Letting the wrapper know the secret without communicating it to
     the rest of the known universe.  Keeping it in a file which is mode
     0400, owned by root, is probably as good as you can get --- but this
     is a problem that the SSL-Apache variants must be dealing with
     somehow regardless.

Of course, the server can't authenticate itself by just supplying the
secret to the wrapper in argv[] or the environment --- that *would*
advertise it to the rest of the known universe (via 'ps axleww', or
the moral equivalent on other systems).  However, sticking a digest of
the shared secret, a per-exec() nonce value, the filename to be
executed, the args, and the environment, and putting that digest in
argv somewhere --- all that might be the basis of a more usable scheme.

(NB that this scheme is deliberately modeled on HTTP digest auth, and
a good long look at the weaknesses in digest auth that the IESG keeps
bitching about might be useful before anyone goes off and actually
implements it.  I'm afraid I don't know in detail exactly *what* they
don't like about digest auth, but I do know they are unhappy).

Of course, the preceding discussion has assumed that you trust the
server itself to decide that it is safe to run a particular binary
with a particular uid, and that all the wrapper needs to verify is
that the instructions it was given came from the web server, and were
not forged or manipulated by any man-in-the-middle.

I'm not entirely comfortable with that assertion myself, and I'm not
sure I'm the only one.  However, if we're aware of that at a risk, we
can at least paint it in red, and have the configure script print a
warning and ask for confirmation before anyone turns it on...


View raw message