Setuid shell scripts (was System V Release 4 ...)
Kenneth Almquist
ka at june.cs.washington.edu
Thu Oct 20 04:07:52 AEST 1988
John Chambers asks:
> To be more specific, I'd sure like to know what it is about the
> shell programming languages (Bourne, C, K, T, etc...) that make
> them more risky than a C program.
Here is a possibly incomplete list of problems:
1. The behavior of shell scripts can depend upon the environment variables
passed in to them. The fix to explicitly set every shell variable
that your shell procedure uses. Explicitly set shell variables to
the empty string rather than assuming they will be initialized to
the empty string by default. More important, explicitly set all shell
variables that the shell refers to implicitly. This includes things
like PATH and IFS.
2. The #! passes the name of the shell script as argv[1], but the shell
does not understand about this convention and will interpret argv[1]
as an option rather than as a file name if the first character of
argv[1] is a minus sign. The fix is to write a little stub program
in C for each setuid shell procedure. The stub program is setuid, and
simply does an exec of the shell with argv[1] set to the full path
name of the actual shell procedure. Since the path name of the shell
procedure is hard coded into the stub, it is guaranteed not to start
with a minus sign. The file containing the shell procedure should not
be either setuid or executable, to ensure that all user invoke the
stub rather than running the shell procedure directly.
Aside from problems 1 and 2, there are also some more general issues:
3. People tend to use the shell for quick hacks which work right in most
cases. But being a little bit insecure is like being a little bit
pregnant. The fix is to put as much thought into writing a setuid
shell procedure as you would into writing a setuid C program. In fact,
writing a setuid shell procedure is *more* difficult that writing a
setuid C program because the semantics of C are simpler.
4. When you write a shell procedure your code depends upon a large body
of software: the shell and also all the programs that your shell
procedure invokes. These programs change. Usually the changes are
backward compatible enough for most purposes, but they may not achieve
the level of backward compatibility required to preserve the security
of a setuid shell script. For example, csh doesn't have IFS. If IFS
were added to csh, most csh shell scripts would continue to work, but
setuid csh scripts would have to be modified to set IFS to a standard
value. The fix is to write setuid programs in C.
OK, that last sentence deserves half a ":-)", but most of the time it's
not worth the trouble to write a setuid program as a shell procedure when
you have C available. An exception is when you need to invoke an operation
(such as ps(1)) which requires you to run a separate program. This is
enough of a pain to do without the shell (note that popen invokes the shell)
that I might use a setuid shell procedure.
In any case, this discussion started with the claim that System V Release 4
would ignore the setuid bits when interpreting "#!". This affects various
interpreted languages like ICON, but as I explained in point 2 above, setuid
shell procedures implemented using a C language stub (which is the only way
I know of to implement setuid shell procedures if you want securely) don't
use the #! facility at all.
Kenneth Almquist
More information about the Comp.unix.wizards
mailing list