SETUID STRIPTS ARE A SECURITY HOLE

John Haxby jch at dyfed.rdg.dec.com
Tue Nov 27 21:02:00 AEST 1990


In article <108862 at convex.convex.com>, tchrist at convex.COM (Tom Christiansen) writes:

|> 
|> When you execute a shell script, what really happens is that the kernel
|> (at least, modern ones) opens the file you asked it to run, sees the magic
|> number of "#!", and then calls the interpreter following that to run the
|> script for you.  The problem is that it passes the name of the script to
|> the shell, and the shell must then reopen the script.  That means we
|> opened the script twice.
|> 
|> Consider the following scenario:  /usr/local/bin/zot is a suid shell
|> script.  ~/snark is a symlink pointing to zot.  ~/gotcha is some
|> program that if run as root would compromise security, such as by
|> giving me a root shell.
|> 
|> I type something like "nice +64 snark &" and let the kernel ever so
|> slowly decide to call the shell with an argument of snark.  It's
|> already set the euid to root because it's pointing to zot, which is
|> suid root.  Now the shell ever so slowly starts up.  In the meantime, I
|> make snark point not to zot but to gotcha.  Bingo!  By the time the
|> suid shell opens snark, it gets gotcha instead of zot, and the whole
|> system is down the tubes.

This works, and prevents any symbolic link diversion:

-----------------
#!/bin/sh /usr/local/bin/zot

: do something suid
echo $0 $*
-----------------

This works because the #! mechanism allows you to pass a single
argument to the interpreter (you can have executable makefiles
by starting them with "#!/bin/make -f").  The argument is taken from
the original file before the shell is exec'd thereby preventing
the symlink nastiness.  The only side-effect of this is that the
shell script should expect to ignore $1--it will normally be the
name of the shell script, it will be the name of the bogus shell
script if someone is trying to break into it.

Setuid shell scripts are no more inherently insecure than are setuid C
programs -- you have to be careful with both.

I tried this out on ULTRIX 4.1 and it works just fine.  To be fair,
I was unable to reproduce the symptoms of the hack under 4.1 and I
the argument passing didn't work too well under 4.0; but when I last
did it on a 3.1 machine, the hack and fix worked just fine.
-- 
-------
John Haxby, Definitively Wrong.
Digital				<jch at wessex.rdg.dec.com>
Reading, England		<...!ukc!wessex!jch>



More information about the Comp.unix.shell mailing list