[comp.unix.questions] setuid shell scripts

dave@murphy.UUCP (11/25/86)

It works on BSD4.2 and 4.3 systems.  I'm pretty sure it does not work on
V7 and SysIII; I can't say for SysV or any other variations.  But, for BSD
systems, you can put the setuid bit on a shell script and it will work as
you expect -- provided that you remember to put an interpreter-specifier
line at the beginning of the script, such as:

#!/bin/csh
 
 or

#!/bin/sh

to specify which shell to run to execute the script.

Use of this feature poses a number of security problems, since shell scripts
aren't usually written with security in mind.  You'll have to evaluate the
risks and benefits for your installation; keep in mind, though, that even if
all of your users are trusted, it's awfully easy to wipe out an entire system
with a faulty shell script running under root, so test your scripts carefully
before installing them with the setuid bit turned on.  At the least, you
should reset $PATH at the beginning of the script so that it contains only
trusted directories (and definitely *not* "."!).

---
It's been said by many a wise philosopher that when you die and your soul
goes to its final resting place, it has to make a connection in Atlanta.

Dave Cornutt, Gould Computer Systems, Ft. Lauderdale, FL
UUCP:  ...{sun,pur-ee,brl-bmd}!gould!dcornutt
 or ...!ucf-cs!novavax!houligan!dcornutt
ARPA: wait a minute, I've almost got it...

"The opinions expressed herein are not necessarily those of my employer,
not necessarily mine, and probably not necessary."

avolio@decuac.DEC.COM (Frederick M. Avolio) (11/28/86)

In article <13@houligan.UUCP>, dave@murphy.UUCP (Rael's brother John) writes:
> It works on BSD4.2 and 4.3 systems.  ...
> Use of this feature poses a number of security problems, since shell scripts
> aren't usually written with security in mind.  ...

Regarding security problems...  You may as well just write a one line
C program that exec's the shell and make *that* setuid to root because
having a setuid shell script causes *the exact same behavior*.  In
other words, a shell script that looks like:

	#! /bin/sh
	date
	exit 0

and has the setuid bit set and is owned by root and readable by anyone
is like having no password on the root account.

Fred

mangler@cit-vax.Caltech.Edu (System Mangler) (11/30/86)

In article <1112@decuac.DEC.COM>, avolio@decuac.DEC.COM (Frederick M. Avolio) writes:
>	#! /bin/sh
>	date
>	exit 0
>
> and has the setuid bit set and is owned by root and readable by anyone
> is like having no password on the root account.     ^^^^^^^^

Make that "executable", not "readable".

In case it is not COMPLETELY clear yet:  the example can be shortened to
	#!/bin/sh

i.e. no commands at all, and it still gives the opportunist an unrestricted
setuid shell, just by running it with argv[0] starting with "-", which can
be typed in a few seconds.  This is true of both sh and csh, with or without
-f.  The only way to prevent this abuse is to not allow execute access.

Better yet, DON'T MAKE SETUID SHELL SCRIPTS.  Delete the ones you have.

(Yes, we got munched in this way.  Funny thing was, the setuid-root shell
script was created by the same superuser who makes the biggest fuss about
security...  So I don't believe in hushing up security holes).

Don Speck   speck@vlsi.caltech.edu  {seismo,rutgers,ames}!cit-vax!speck

bsteve@gorgo.UUCP (11/30/86)

In article <13@houligan.UUCP>, dave@murphy.UUCP (Rael's brother John) wrote:
   avolio@decuac.UUCP in comp.unix.ques replied:

>> It works on BSD4.2 and 4.3 systems.  ...
>> Use of this feature poses a number of security problems, since shell scripts
>> aren't usually written with security in mind.  ...
>
>Regarding security problems...  You may as well just write a one line
>C program that exec's the shell and make *that* setuid to root because
>having a setuid shell script causes *the exact same behavior*.  In
>other words, a shell script that looks like:
>
>	#! /bin/sh
>	date
>	exit 0
>
>and has the setuid bit set and is owned by root and readable by anyone
>is like having no password on the root account.

To be more correct, it is not even necessary that the shell script be
readable in the case of most 4.2 implementations. Setuid-root shell scripts
should simply not be used at all. Anyone unclear regarding why this is may
write me personally.

  Steve Blasingame (Oklahoma City)
  ihnp4!occrsh!gorgo!bsteve
  bsteve@eris.berkeley.edu

jxs7451@ritcv.UUCP (12/01/86)

>Make that "executable", not "readable".

The problem is that for a sh or csh (not ksh i think) shell script to 
execute it has to be executable AND readable.  At least on AIX as recent
as C39C and 4.3 BSD on a 780.  I don't know the big security hole in suid
scripts are, but then again I dont think RIT would want me to know because
i am just a student.  Oh well.

J. Smith
ritcv!jxs7451

The things i say here have nothing to do with my school or my former employer,
other than the fact that I use their machines.

hartley@uvm-gen.UUCP (Stephen J. Hartley) (12/01/86)

< Summary: unconditionally insecure
< Posted: Sat Nov 29 23:25:37 1986
< 
< In case it is not COMPLETELY clear yet:  the example can be shortened to
< 	#!/bin/sh
< 
< i.e. no commands at all, and it still gives the opportunist an unrestricted
< setuid shell, just by running it with argv[0] starting with "-", which can
< be typed in a few seconds.  This is true of both sh and csh, with or without
< -f.  The only way to prevent this abuse is to not allow execute access.
< 
Does this hole still exist in 4.3 BSD?  I thought it had been fixed.
-- 
	Department of Computer Science and Elec. Eng.	Stephen J. Hartley
USENET:	{decvax,ihnp4}!dartvax!uvm-gen!uvm-cs!hartley	University of Vermont
CSNET:	hartley%uvm@csnet-relay				(802) 656-3330, 862-5323

mjranum@gouldsd.UUCP (Marcus J Ranum) (12/01/86)

In article <13@houligan.UUCP>, dave@murphy.UUCP (Rael's brother John) writes:
> It works on BSD4.2 and 4.3 systems.  ...

	When writing setuid shell scripts it's a good idea to specifically
set the PATH (not including '.' or any WRITEABLE directory)  You also must
avoid any programs that have a shell escape or can call a program with a
shell escape. 
	Usually when I have to do setuid shell scripts, I change directory
to someplace innocuous and unwritable, set the PATH to nothing, and call
*EVERYTHING* with explicit path names. Even then, it's a rotten idea to
use setuid shells when you have a perfectly good C compiler around and can
do a much better job...


-- 
 
TRUST NO-ONE !!   STAY ALERT !!
KEEP YOUR LASER HANDY !!
THE COMPUTER IS YOUR FRIEND !!!

pdg@ihdev.UUCP (P. D. Guthrie) (12/02/86)

In article <416@gouldsd.UUCP> mjranum@gouldsd.UUCP (Marcus J Ranum) writes:
]In article <13@houligan.UUCP>, dave@murphy.UUCP (Rael's brother John) writes:
]] It works on BSD4.2 and 4.3 systems.  ...
]
]	When writing setuid shell scripts it's a good idea to specifically
]set the PATH (not including '.' or any WRITEABLE directory)  You also must
]avoid any programs that have a shell escape or can call a program with a
]shell escape. 
]	Usually when I have to do setuid shell scripts, I change directory
]to someplace innocuous and unwritable, set the PATH to nothing, and call
]*EVERYTHING* with explicit path names. Even then, it's a rotten idea to
]use setuid shells when you have a perfectly good C compiler around and can
]do a much better job...

Yes, this is good on System V (pick your release), but *not* on
Berkeley.  As has been noted many times, the security bug does not even
run the script to work.  Therefor all of your nicely thought out,
carefull programming could not stop the security hacker who could not
give a hoot what your script does (or does not) because it doesn't
matter.  

Your last sentence sums this discussion on setuid shell scripts up pretty
well.  *Never* have setuid shell scripts on a BSD4.x system unless a)
you don't care who breaks into your machine (some people don't) or b)
you have installed a kernel-kludge to plug the security hole.  Does
anyone have diffs for this they can post?  The last BSD machine I had
access to just went to sourceless Ultrix. Sigh.

-- 

Paul Guthrie					We come in peace,
ihnp4!ihdev!pdg					We bring BEER!

ado@elsie.UUCP (Arthur David Olson) (12/03/86)

> *Never* have setuid shell scripts on a BSD4.x system unless a)
> you don't care who breaks into your machine (some people don't) or b)
> you have installed a kernel-kludge to plug the security hole.  Does
> anyone have diffs for this they can post?

For those without kernel source but with a compelling need for set-user-id
script, a workaround is to begin scripts this way:

	#! /bin/sh /the/name/of/the/script/itself
	shift

So, for example, a script named "/etc/adduser" would begin

	#! /bin/sh /etc/adduser
	shift

Of course, you still get to deal with PATH, IFS, and other such issues in
the script itself.
--
UNIX is a registered trademark of AT&T.
PATH is a trademark of the Port Authority Trans-Hudson.
The set-user-id bit is a patented inspiration of Dennis Ritchie.
Sh is a trademark of the American Librarians Association.
--
	UUCP: ..decvax!seismo!elsie!ado   ARPA: elsie!ado@seismo.ARPA
	DEC, VAX, Elsie & Ado are Digital, Borden & Ampex trademarks.

maart@cs.vu.nl (Maarten Litmaath) (10/24/89)

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

chris@mimsy.umd.edu (Chris Torek) (10/24/89)

In article <20329@mimsy.umd.edu> (look, domain names now!) I wrote:
>\On all of the BSD derivatives on which setuid scripts run setuid,
>\all such setuid scripts are not secure.

In article <3789@solo6.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
>It almost never happens, but this time you seem to be wrong, Chris!

Not really, because I meant `if you write /etc/foo, make it setuid, start
it with ``#! /bin/csh -bf'', and run it, and it runs setuid, then it is
not secure.'

>\You have to write at least one C program.

>Indeed: /bin/indir!  (Formerly /bin/setuid.)

I am not going to promise that /bin/indir will do the trick (having
seen too many ways to fool too many shells), but by using /bin/indir
you have met my restriction (`at least one C program').  I should
rephrase it:

    Given the current kernel implementation, a setuid script is
    not secure unless its `setuid-ness' is provided by a separate
    C program that makes additional security checks (and possibly
    still not even then).
-- 
`They were supposed to be green.'
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

maart@cs.vu.nl (Maarten Litmaath) (10/25/89)

chris@mimsy.umd.edu (Chris Torek) writes:
\In article <20329@mimsy.umd.edu> (look, domain names now!) I wrote:
\>\On all of the BSD derivatives on which setuid scripts run setuid,
\>\all such setuid scripts are not secure.
\
\In article <3789@solo6.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
\>It almost never happens, but this time you seem to be wrong, Chris!
\
\Not really, because I meant `if you write /etc/foo, make it setuid, start
\it with ``#! /bin/csh -bf'', and run it, and it runs setuid, then it is
\not secure.'

I'm sure this was what you meant, but it wasn't what you said!  (Check again.)
Allright, you have already posted an article explaining the race condition,
but here's another story anyway, which explains how indir(1) can get things
right.  Enjoy.
----------8<----------8<----------8<----------8<----------8<----------
			Setuid Shell Scripts
			--------------------
			how to get them safe

			  Maarten Litmaath
			  (maart@cs.vu.nl)


Consider a setuid root shell script written in Bourne shell command language
and called `/bin/powerful'.
The first line of the script will be (without indentation!):

	#!/bin/sh

If it doesn't begin with such a line, it's no use to chmod it to 6755 or
whatever, because in that case it's just a shell script of the `old' kind:
the Bourne shell receives an exec format error when trying to execute it, and
decides it must be a shell script, so it forks a subshell with the script name
as argument, to indicate from which file the commands are to be read.
Shell scripts of the `new' kind are treated as follows: the kernel discovers
the magic number `#!' and tries to execute the command interpreter pointed out,
which may be followed in the script by 1 argument.
Before the exec of the interpreter the uid and gid fields somewhere in the user
structure of the process are filled in.
Setuid script scheme (kernel manipulations faked by C routines):

	execl("/bin/powerful", "powerful", (char *) 0);

	  |
	  V

	setuid(0);
	setgid(0);      /* possibly */
	execl("/bin/sh", "sh", "/bin/powerful", (char *) 0);

Now, what if the name of the very shell script were e.g. "-i"? Wouldn't that
give a nice exec?

	execl("/bin/sh", "sh", "-i", (char *) 0);

So link the script to a file named "-i", and voila!
Yes, one needs write permission somewhere on the same device, if one's
operating system doesn't support symbolic links.

What about the csh command interpreter? Well, 4.2BSD provides us with a csh
which has a NEW option: "-b"! Its goal is to avoid just the thing described
above: the mnemonic for `b' is `break'; this option prevents following
arguments of an exec of /bin/csh from being interpreted as options...
The csh refuses to run a setuid shell script unless the option is present...
Scheme:
	#!/bin/csh -b
	...

	execl("-i", "unimportant", (char *) 0);

	  |
	  V

	setuid(0);
	setgid(0);
	execl("/bin/csh", "csh", "-b", "-i", (char *) 0);

And indeed the contents of the file "-i" are executed!
However, there's still another bug hidden, albeit not for long!
What if I could `get between' the setuid()/setgid() and the open() of the
command file by the command interpreter?
In that case I could unlink() my link to the setuid shell script, and quickly
link() some other shell script into its place, couldn't I?
Right.
Yet another source of trouble for /bin/sh setuid scripts is the reputed IFS
shell variable. Of course there's also the PATH variable, which might cause
problems. However, one can circumvent these 2 jokers easily.
A solution to the link()/unlink() problems would be the specification of the
full path of the script in the script itself:

	#!/bin/sh /etc/setuid_script
	shift		# remove the `extra' argument
	...

Some objections:
1)
	currently the total length of shell + argument mustn't exceed 32 chars
	(easily fixed);
2)
	4.[23]BSD csh is expecting a `-b' flag as the first argument, instead
	of the full path (easily fixed);
3)
	the interpreter gets an extra argument;
4)
	the difficulty of maintaining setuid shell scripts increases - if one
	moves a script, one shouldn't forget to edit it... - editing in turn
	could turn off the setuid bits, so one shouldn't forget to chmod(1)
	the file `back'... - conceptually the solution above isn't `elegant'.

How does indir(1) tackle the problems? The script to be executed will look
like:
	#!/bin/indir
	#?/bin/sh /etc/setuid_script
	...

Indir(1) will try to open the script and read the `#?' line indicating the
real interpreter and a safe (absolute) pathname of the script. But remember:
the link to the script might have been quickly replaced with a link to another
script, i.e. how can we trust this `#?' line?
Answer: if and only if the file we're reading from is SETUID (setgid) to the
EFFECTIVE uid (gid) of the process, we know we're executing the original
script (to be 100% correct: the original link might have been replaced with a
link to ANOTHER setuid script of the same owner -> merely a waste of time).
To reliably check the condition stated above, we use fstat(2) on the file
descriptor we're reading from. Can you figure out why stat(2) would be
insecure?
To deal with IFS, PATH and other environment problems, indir(1) resets the
environment to a simple default:

	PATH=/bin:/usr/bin:/usr/ucb

When you need e.g. $HOME, you should get it from /etc/passwd instead of
trusting what the environment says. Of course with indir(1) problem 4 remains.

				--------
-- 
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

terryl@tekcrl.LABS.TEK.COM (10/25/89)

In article <3803@solo7.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
+chris@mimsy.umd.edu (Chris Torek) writes:
+\In article <20329@mimsy.umd.edu> (look, domain names now!) I wrote:
+\>\On all of the BSD derivatives on which setuid scripts run setuid,
+\>\all such setuid scripts are not secure.
+\
+\In article <3789@solo6.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
+\>It almost never happens, but this time you seem to be wrong, Chris!
+\
+\Not really, because I meant `if you write /etc/foo, make it setuid, start
+\it with ``#! /bin/csh -bf'', and run it, and it runs setuid, then it is
+\not secure.'
+
+I'm sure this was what you meant, but it wasn't what you said!  (Check again.)
+Allright, you have already posted an article explaining the race condition,
+but here's another story anyway, which explains how indir(1) can get things
+right.  Enjoy.

    Not to pick nits, but Chris was *right* *both* times. As you have quoted
him above, he said "On all of the BSD derivatives on which setuid scripts run
setuid, all such setuid scripts are not secure."; implicit in this sentence
is the fact that the only way to get a setuid script to run setuid, one must
use the #! mechanism. So while Chris did not spell this out explicitly in his
first posting, he did in his second. But he was still right the first time...


			Terry Laskodi
			     of
			Tektronix

PS:
     Is it time to post another way to breach security with a setuid shell
script that does NOT depend on the race condition with "unlink"????

maart@cs.vu.nl (Maarten Litmaath) (10/25/89)

terryl@tekcrl.LABS.TEK.COM writes:
\In article <3803@solo7.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
\+chris@mimsy.umd.edu (Chris Torek) writes:
\+\In article <20329@mimsy.umd.edu> (look, domain names now!) I wrote:
\+\>\On all of the BSD derivatives on which setuid scripts run setuid,
\+\>\all such setuid scripts are not secure.
\+\
\+\In article <3789@solo6.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
\+\>It almost never happens, but this time you seem to be wrong, Chris!
\+\
\+\Not really, because I meant `if you write /etc/foo, make it setuid, start
\+\it with ``#! /bin/csh -bf'', and run it, and it runs setuid, then it is
\+\not secure.'
\+
\+I'm sure this was what you meant, but it wasn't what you said!  (Check again.)
\+Allright, you have already posted an article explaining the race condition,
\+but here's another story anyway, which explains how indir(1) can get things
\+right.  Enjoy.
\
\    Not to pick nits, but Chris was *right* *both* times. As you have quoted
\him above, he said "On all of the BSD derivatives on which setuid scripts run
\setuid, all such setuid scripts are not secure."; implicit in this sentence
\is the fact that the only way to get a setuid script to run setuid, one must
\use the #! mechanism. So while Chris did not spell this out explicitly in his
\first posting, he did in his second. But he was still right the first time...

Yeah, one must use the #! mechanism; SO WHAT!?  I never denied that!
And I showed how safe setuid scripts (NOTE: Chris didn't even say *shell*
scripts) could be created.  You want an example?  Right, put the following
in a file /etc/fubar:

	#!/bin/sh /etc/fubar
	echo "Am I right or am I right?"

You're a pretty smart fellow if you can break this one (or you're root).

\PS:
\     Is it time to post another way to breach security with a setuid shell
\script that does NOT depend on the race condition with "unlink"????

Yeah, go right ahead.
-- 
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

peter@ficc.uu.net (Peter da Silva) (10/26/89)

Another possible solution to thhe setuid shell script problem would be for
the system to feed the script to the shell via an open file descriptor,
say... descriptor 3. This could support existing shells by passing
/dev/fd3 on the command line.
-- 
Peter da Silva, *NIX support guy @ Ferranti International Controls Corporation.
Biz: peter@ficc.uu.net, +1 713 274 5180. Fun: peter@sugar.hackercorp.com. `-_-'
"That particular mistake will not be repeated.  There are plenty of        'U`
 mistakes left that have not yet been used." -- Andy Tanenbaum (ast@cs.vu.nl)

tjr@cbnewsc.ATT.COM (thomas.j.roberts) (10/26/89)

From article <3806@solo7.cs.vu.nl>, by maart@cs.vu.nl (Maarten Litmaath):
> terryl@tekcrl.LABS.TEK.COM writes:
> 
> Yeah, one must use the #! mechanism; SO WHAT!?  I never denied that!
> And I showed how safe setuid scripts (NOTE: Chris didn't even say *shell*
> scripts) could be created.  You want an example?  Right, put the following
> in a file /etc/fubar:
> 
> 	#!/bin/sh /etc/fubar
> 	echo "Am I right or am I right?"
> 
> You're a pretty smart fellow if you can break this one (or you're root).

I run on System V, and have never used #!. However, I believe this approach
will cause serious problems:
	set IFS=c, and place an appropriate program named "e" into
	your path. The shell will execute "e" with argument 'ho Am I ...?'.

This is only one of many problems with SUID shell scripts. Fooling around
with PATH, IFS, PS1 and other internally-used environment variables can
cause the shell to do unexpected things. The problems with SUID shell-scripts
are inherent, given the tremendous complexity of the shell - even if you 
modify the shell to close all of the known "SUID holes", you will never
know when you have found them all.

Tom Roberts
att!ihnet!tjr

terryl@tekcrl.LABS.TEK.COM (10/26/89)

In article <3806@solo7.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
terryl@tekcrl.LABS.TEK.COM writes:
\In article <3803@solo7.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
\+chris@mimsy.umd.edu (Chris Torek) writes:
\+\In article <20329@mimsy.umd.edu> (look, domain names now!) I wrote:
\+\>\On all of the BSD derivatives on which setuid scripts run setuid,
\+\>\all such setuid scripts are not secure.
\+\
\+\In article <3789@solo6.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
\+\>It almost never happens, but this time you seem to be wrong, Chris!
\+\
\+\Not really, because I meant `if you write /etc/foo, make it setuid, start
\+\it with ``#! /bin/csh -bf'', and run it, and it runs setuid, then it is
\+\not secure.'
\+
\+I'm sure this was what you meant, but it wasn't what you said!  (Check again.)
\+Allright, you have already posted an article explaining the race condition,
\+but here's another story anyway, which explains how indir(1) can get things
\+right.  Enjoy.
\
\    Not to pick nits, but Chris was *right* *both* times. As you have quoted
\him above, he said "On all of the BSD derivatives on which setuid scripts run
\setuid, all such setuid scripts are not secure."; implicit in this sentence
\is the fact that the only way to get a setuid script to run setuid, one must
\use the #! mechanism. So while Chris did not spell this out explicitly in his
\first posting, he did in his second. But he was still right the first time...

>Yeah, one must use the #! mechanism; SO WHAT!?  I never denied that!
>And I showed how safe setuid scripts (NOTE: Chris didn't even say *shell*
>scripts) could be created.  You want an example?  Right, put the following
>in a file /etc/fubar:
>
>	#!/bin/sh /etc/fubar
>	echo "Am I right or am I right?"
>
>You're a pretty smart fellow if you can break this one (or you're root).

     What needs to be added is the following fact: If a setuid shell script
uses ANY NON-BUILTIN command, I can become the owner of said setuid shell
script in a manner of minutes. In your above example, if the command "echo"
is not builtin to the shell, then yes, I can break the script in a manner of
minutes. If "echo" is builtin to the shell, then, no, I can't break the script.

>\PS:
>\     Is it time to post another way to breach security with a setuid shell
>\script that does NOT depend on the race condition with "unlink"????
>
>Yeah, go right ahead.

     Well, now I can't tell if you're being sarcastic or not, but I'll wait
a few days before I post it. One small caveat, though: I do need one writable
directory, but it can be anywhere in the file system.....



				Terry Laskodi
				     of
				Tektronix

ip@me.utoronto.ca (Bevis Ip) (10/26/89)

>>Yeah, one must use the #! mechanism; SO WHAT!?  I never denied that!
>>And I showed how safe setuid scripts (NOTE: Chris didn't even say *shell*
>>scripts) could be created.  You want an example?  Right, put the following
>>in a file /etc/fubar:
>>
>>	#!/bin/sh /etc/fubar
>>	echo "Am I right or am I right?"
>>
>>You're a pretty smart fellow if you can break this one (or you're root).
>

Sigh... on some systems (SGI, for example), your script will never get
parsed after the first character.  There are more than just the
kernel which make setuid script insecure...

bevis
-- 
Bevis Ip                <>  ip@me.toronto.edu, ip@me.utoronto.ca
University of Toronto   <>  {pyramid,uunet}!utai!me!ip
Mechanical Engineering  <>  {allegra,decwrl}!utcsri!me!ip