Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!snorkelwacker!bloom-beacon!eru!luth!sunic!mcsun!hp4nl!star.cs.vu.nl!maart From: maart@cs.vu.nl (Maarten Litmaath) Newsgroups: comp.unix.questions Subject: setuid shell scripts (was: Re: Running processes as root) Message-ID: <3789@solo6.cs.vu.nl> Date: 23 Oct 89 22:40:38 GMT References: <21240@adm.BRL.MIL> <20329@mimsy.umd.edu> Organization: V.U. Informatica, Amsterdam, the Netherlands Lines: 133 chris@mimsy.umd.edu (Chris Torek) writes: \... \On all of the BSD derivatives on which setuid scripts run setuid, \all such setuid scripts are not secure. It almost never happens, but this time you seem to be wrong, Chris! \>... you must think ahead to restrict the user to executing \>only the script you've choosen \ \With the existing implementations, this is not possible. (Sorry.) Ahum. \You have to write at least one C program. Indeed: /bin/indir! (Formerly /bin/setuid.) Here's the manpage. Source available soon in comp.sources.unix. INDIR(1) USER COMMANDS INDIR(1) NAME indir - run (setuid) (shell) scripts indirectly SYNOPSIS #!/bin/indir #?... DESCRIPTION Indir is not executed from a shell normally. Instead it can be used as the interpreter for shell scripts that: 1) need to be run setuid to someone else, or 2) fail to meet the constraints for a `#!' line (see execve(2)). Indir is invoked by making the first line of the script #!/bin/indir rather than the usual #!/bin/sh Indir tries to open the script for reading. If successful it discards the first line (containing `#!/bin/indir') and tries to read a line formatted as follows: #?absolute-path-of-interpreter arguments Whitespace around the `#?' magic number is discarded. The interpreter as well as the arguments are subject to the `tilde convention': a leading string `~user' is expanded to the home directory of `user', where `user' is the longest string of alphanumeric characters immediately following the `~'. If this string equals the null string, the login name of the effective uid is used. Furthermore an argument consisting of a single `%' is expanded to the name of the script. However, if the file being executed is a setuid script, the expansion is inhi- bited (see below). Examples: #?/bin/csh -bf /usr/etc/setuid_script -v #? ~/bin/my_interpreter -f ~john/foo/bar #?/bin/sed -n -f % A `#?' line is limited to 256 characters. However, if the line ends in a backslash (`\'), the next line is assumed to contain further arguments after a mandatory leading `#?', Sun Release 4.0 Last change: Oct 21, 1989 1 INDIR(1) USER COMMANDS INDIR(1) and so on. There is a system-imposed limit on the total number of characters present in the argument list. To avoid `linking tricks' through which uncontrolled privileges of the owner of the file could be acquired, 3 measures have been taken for setuid scripts: 1) the script must contain its own safe invocation, that is the `#?' line; `%' arguments will not be expanded; 2) the environment is reset to a simple default: PATH=/bin:/usr/bin:/usr/ucb 3) before the final execv(2) indir checks if the owner and mode of the script are still what they are supposed to be (using fstat(2)); if there is a discrepancy, indir will abort with an error message. Indir will only exec a pathname beginning with a `/'. Of course indir can be `fooled' by supplying dubious arguments to the interpreter, like relative pathnames. Furthermore it is a mistake to let any of the directory components of an ultimate path be writable by others. In our first example `/', `/bin', `/usr' and `/usr/etc' should not be writable for ordinary users. AUTHOR Maarten Litmaath @ VU Informatika Amsterdam (maart@cs.vu.nl) SEE ALSO sh(1), csh(1) BUGS The maintenance of setuid scripts is a bit annoying: if a script is moved, one must not forget to change the path men- tioned in the script. Possibly the editing causes the setuid bit to get turned off. -- A symbolic link is a POINTER to a file, | Maarten Litmaath @ VU Amsterdam: a hard link is the file system's GOTO. | maart@cs.vu.nl, mcsun!botter!maart