httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r..@ai.mit.edu (Robert S. Thau)
Subject Re: setuid control WITHOUT running as root
Date Mon, 03 Jun 1996 15:28:54 GMT
  It would be relatively easy  
  to setup a test for giveaway chowns and configure the compile of
  sucgi.c to be that next bit more paranoid. Neither FreeBSD or Solaris
  have this problem, so I'm not too concerned about the restriction.

Unfortunately, while giveaway chowns may make it easier to exploit the
problem, running on a system without them doesn't make the problem go
away.

For instance, on just about any Unix variant, I can set up a private
'bin' directory, writable only by me, and put commands in it, writable
only by me, and allow other people to run those commands.  I can do that
secure in the knowledge that a potential attacker who wanted to subvert
my account, gain access to my private data, send mail in my name, or
whatever could not use those commands to do anything with them which the
attacker could not have done just as easily *without* access to the stuff
in my private bin.

However, if the attacker has access to your modified sucgi wrapper, the
situation changes --- with it, attackers can effectively forge a suid bit
on any of those files.  This offers any number of "useful" possibilities.
If the command can be coerced into reading a file and spitting out its
contents, my private data is compromised.  (A common trick is to tell the
program to use the target file as some kind of config file, and read its
text out of the syntax errors).  If the command can be coerced into writing
a file, the attacker can plant a trojan horse (for me and anyone else with
my bin on their path).  And if the command has a shell escape, well...
*that* I hope I don't have to spell out.

(Yes, I probably should have mentioned this yesterday, but it was late, and
I was tired, which is the wrong condition to be in when designing or eval-
uating a security policy).

The way that cgiwrap, and Jason's original sucgi-wrapper, both get around
this difficulty is that they only allow the wrapper to provide suid treatment
for files which are in particular directories, where everything in that 
directory can be assumed to have been properly vetted for suid use (in
particular, to perform all the appropriate paranoid checks).  In effect,
the presence of a file in *that* directory is used as a marker to indicate
that the command in question can safely be run setuid.  

Now, designating directories is only one way of providing such a marker;
you could, for instance, put a cryptographic checksum of the file in an
"OKsuid" file in the same directory as the file itself, and require all
the file permissions on the directory, the command file, and the OKsuid
file, to *all* be secure enough that an attacker would require at least
write access to the victim's file structures in order to forge the setup.
(Of course, on systems with giveaway chowns, no such assurance is possible,
and on those at *least*, you need other arrangements).

In fact, you could conceivably use the file system suid bit itself as
such a marker --- in which case all the rest of this machinery would
become unnecessary.  (I think sameer mentioned that there were cases
in which he thought that this might be a bad idea, but I'm not sure
that I understood the exact nature of the attacks he was concerned
about.  Sameer, if you could spell it out a little more, I'd
appreciate it).

One last concern --- as long as we're on the subject of suid files and the
appropriate levels of paranoia pertaining thereto.  It is fairly well known
that suid files need to be paranoid about their environment.  Because of this,
on systems with shared libraries, ld.so ignores LD_LIBRARY_PATH when the
program it is linking at runtime is being run setuid, to keep trojan-horse
code from being introduced via bogus shared libraries.  However, when the
program is being run effectively-suid by a wrapper, ld.so may not have any
easy way of knowing that it has been run setuid, in which case the check
will fail and the trojan-horse code will be activated.

The attack which this *might* allow is for an attacker to set LD_LIBRARY_PATH
to include a directory with the trojan-horse libs, and then invoke a target
script (in this case, it doesn't really matter what the script is supposed
to do) through the wrapper.  Because the wrapper itself is suid, it will not
be linked with the bogus shared libs.  However, if the wrapper passes the
environment on to the target script with the same LD_LIBRARY_PATH value, and
ld.so then does its usual thing, then the trojan-horse libs *will* be active
in the target.  

I honestly don't know what measures Jason's original sucgi wrapper or
CGIwrap take against this sort of attack; however, Randy's modified
sucgi wrapper would appear to be vulnerable, at least at first glance.
One possible fix for this is to simply delete LD_LIBRARY_PATH from the
environment if it is set (or better yet, just log the event and refuse
to do anything).

(BTW, Randy, since your sucgi.c differs significantly from Jason's
original, perhaps you should call it something else, if only to avoid
confusion).

rst


Mime
View raw message