[comp.unix.wizards] Guide to writing secure setuid programs?

riddle@woton.UUCP (Prentiss Riddle ) (03/09/88)

There's been a recent flurry of discussion in comp.bugs.sys5 about a
few specific security pitfalls to avoid in writing setuid programs.  I
get the feeling that this is just the tip of the iceberg. 

Can anyone point us to a more comprehensive guide to how to write good
setuid programs?  If you've got something on-line, please consider
posting it; if you know of good book or journal references, please mail
them to me and I will summarize. 

And if nothing of this sort exists, perhaps it's time to write one. 
Thanks. 

-- Prentiss Riddle ("Aprendiz de todo, maestro de nada.")
-- Opinions expressed are not necessarily those of my employer.
-- riddle%woton.uucp@im4u.utexas.edu  {ihnp4,uunet}!ut-sally!im4u!woton!riddle

jmc@ptsfa.UUCP (Jerry Carlin) (03/11/88)

In article <1037@woton.UUCP> riddle@woton.UUCP (Prentiss Riddle ) writes:
>Can anyone point us to a more comprehensive guide to how to write good
>setuid programs?

See "How To Write a Setuid Program" in ;login:, volume 12, number 1,
Jan/Feb 1987 by Matt Bishop, Research Institute for Advanced Computer
Science, NASA Ames Research Center, Moffett Field, CA 94035.

-- 
Jerry Carlin (415) 823-2441 {ihnp4,lll-crg,ames,qantel,pyramid}!ptsfa!jmc
soon: {ihnp4,lll-crg,ames,qantel,pyramid}!pacbell!ptsfa!jmc
To dream the impossible dream. To fight the unbeatable foe.

dwm@ihlpf.ATT.COM (Meeks) (03/11/88)

In article <1037@woton.UUCP>, riddle@woton.UUCP (Prentiss Riddle ) writes:
> There's been a recent flurry of discussion in comp.bugs.sys5 about a
> few specific security pitfalls to avoid in writing setuid programs.  I
> get the feeling that this is just the tip of the iceberg. 
> 
> Can anyone point us to a more comprehensive guide to how to write good
> setuid programs?  If you've got something on-line, please consider
> posting it; if you know of good book or journal references, please mail
> them to me and I will summarize. 
> 
> And if nothing of this sort exists, perhaps it's time to write one. 
> Thanks. 
> 
> -- Prentiss Riddle ("Aprendiz de todo, maestro de nada.")
> -- Opinions expressed are not necessarily those of my employer.
> -- riddle%woton.uucp@im4u.utexas.edu  {ihnp4,uunet}!ut-sally!im4u!woton!riddle

----------------------------------------------------

There are some very good tips on how to code secure code in the book:

	UNIX SYSTEM SECURITY: by P. H. Wood and S. G. Kochan

This book is published by: Hayden Books. In the book are examples of how
to write good code that will help protect suid/sgid programs. It actually
includes a set of guidelines to follow: First item: do not write them in the
first place, there are other ways to achieve the same effect.



                //-n-\\				 Daniel W. Meeks
        _____---=======---_____			(ihnp4!ihlpf!dwm)
    ====____\   /.. ..\   /____====
  //         ---\__O__/---        \\	Enterprise... Surrender or we'll
  \_\                            /_/	send back your *&^$% tribbles !!

scl@virginia.acc.virginia.edu (Steve Losen) (03/12/88)

I have no guide for writing setuid programs, but here are a few
ideas that come to mind:

1)	There's a big difference between setuid to root and setuid to
	an ordinary user.  This should be obvious because of the many
	operations that only root can do.  One should always endeaver to
	make a program setuid to some non-root user if at all possible.
	If a program is setuid to a non-root user it should revert back
	to the real user whenever possible so that the program can access
	all of the user's files.  We all know what a pain it is that lp(1)
	can't open any files that user "lp" can't access (which may
	include files that the real user can access.)

2)  Avoid setuid if you can.  I once wrote a very simple print spooler
	that puts files in a directory where they are picked up periodically
	by a daemon to be printed.  I made the directory 777 instead of using
	setuid-to-lp fraud.  Sure a malicious user can remove files in the
	print queue. So what?  To my knowlege, no one has ever done that in
	the two years since I put the system up.  Ask yourself, "Does this
	really need to be setuid?"  For example, I would *never* make a program
	setuid just so it could write to a protected logfile.  To hell with it.
	make the logfile 622.

3)	Have the setuid program grab all necessary resources at the beginning
	and revert back to the real user.  For example, once you open a file
	you can revert back to the real user before reading or writing.
	This little trick can be very handy for instructors who want their
	students to turn in assignments to the instructor's protected directory
	from the student's protected directory.  Sound like job for root?
	Nope! Write a setuid-to-instructor program that creat(2)'s a file in
	the instructors protected directory.  Now revert back to the real user
	(the student), open the assignment, and copy it to the fd that was
	creat(2)'ed earlier.  As a matter of fact, I heard a horror story
	about another such turn-un program.  The program was setuid to
	root and it prompted for source and destination file names.
	The source name was appended to the student's home directory
	while the destination name was appended to the instructor's "turn-in"
	directory and the copy was done.  Unfortunately, the programmer
	forgot about "../../.." and students quickly learned that they could
	copy any file anywhere with this program.
	(This was taken from comp.risks, a newsgroup I highly recommend.)

	Another thing you can do is set up a system so that all of its
	sensitive files and directories are within a single subtree.
	Make the directory at the top of the subtree 700 to keep ordinary
	users out.  But within the subtree loosen the permissions.  Make
	directories where users will create files 777.  Make logfiles
	622.  Each program that manipulates this system is setuid to the
	owner of the protected directory.  Upon invocation, the process
	chdirs below the protected directory and reverts back to the real
	user.  Now the process can access both the user's files and the
	sensitive system files.  This sort of design would have solved the
	problem with lp(1).

4)	Instead of making a whole program setuid, identify the portions that
	need special privilege and write small, very specific setuid programs
	to do those tasks.  Fork and/or exec the small programs from the main
	program.  We once had a program that needed to signal another process
	that was owned by a different user.  Instead of making the first
	process setuid to root, we wrote a small setuid to root program to
	send the signal.  To keep normal users from running the little program
	we put it in a special group with mode 4110 and made the first program
	setgid to the special group.

5)	If you MUST write a setuid to root program be VERY careful when
	checking any input or arguments from a user.  Realize that root
	can do amazing things that even an administrator would never do.
	Take unlink(2) in SysV, for example.  Root can unlink a directory,
	disconnecting from the file system any files that were
	in the directory.  Fsck is the only way to relink those files.
	So even if you do an access(2) and find out that "yes, the real user
	can remove file foo" be sure that "foo" is not a directory.
	Root can also unlink "." and ".." .  Another example is
	mount(2).  You have to be root to mount a floppy on a 3b2.  If you
	write a setuid program for your users to mount floppies, you better
	check carefully where the user wants to mount or she could put her
	own "passwd" file on the floppy and mount it on /etc.
	
	In a similar vein, when running in "root" mode, realize that
	environment variables are easy to fake.  Never use the PATH
	environment variable; always fully specify the pathnames of
	any process you exec.  If you exec a process as root, you might
	want to clear the environment first.  Use getpwent instead of $HOME.
	

Well this is certainly a lot more than I first intended to say.
-- 
Steve Losen     scl@virginia.edu
University of Virginia Academic Computing Center

friedl@vsi.UUCP (Stephen J. Friedl) (03/13/88)

In article <1037@woton.UUCP>, riddle@woton.UUCP (Prentiss Riddle ) writes:
> There's been a recent flurry of discussion in comp.bugs.sys5 about a
> few specific security pitfalls to avoid in writing setuid programs.  I
> get the feeling that this is just the tip of the iceberg. 

     A few more notes that I've not seen mentioned.  First,
setuid and setgid programs should be mode --x--x--x so people
like me :-) can't look at them.  When digging for holes on a
machine the first thing I do is run strings on the set[ug]id
programs to look for the standard holes -- you can recognize them
after a while.  If they are execute-only it is tougher both
because I don't know what to try but more importantly, some
programs keep logs that I might not be able to clean up if I
fail.  Making them readonly will frustrate the beginning to
intermediate hacker.  Note that this applies to all setuid
programs, not just ones you contribute to the system.

     If you are writing a program and you need to check the user
of the program, there are some ways *not* to find out who it is.
Disclaimer:  this is all for System V -- my days on a Berkeley
machine were before I learned all about this security stuff.
These may not all apply to your machine.

     Looking at $LOGNAME should *never* be trusted directly as it
can be trivially fooled.  Putting "readonly LOGNAME" in
/etc/profile will frustrate this a little but but not much.
logname(1) and logname(3) look in /etc/utmp to find the user who
logged in on that line.  I dunno, this doesn't strike me as the
best idea.  If you su(1) to another user this won't catch it,
which seems to me to be not what I want.  Note: the 3B2 SVR2 and
SVR3 manual for logname(3) says that the function looks at
$LOGNAME:  it really looks at /etc/utmp and never consults
$LOGNAME.

     Obviously, if the program is set-user-id you can't use
geteuid(2), and if it is set-group-id you can't use getegid(2) --
both will say it is *you* running the program, so assume here
that getuid(2) is used.  While getpwuid(3) can be used to get the
name directly, this doesn't work well if multiple login names
share the same uid ("root", "powerdown", etc.).  My approach is
to trust $LOGNAME if the pw_uid field in /etc/passwd (with
getpwnam(3)) for $LOGNAME matches the return from getuid(2).
Sure, "powerdown" can pretend to be "shutdown" but I have not
seen it be a problem in my systems because important distinctions
get separate accounts with unique uids.  If the two uids do not
match then you simply ignore $LOGNAME and use getpwuid(getuid())
for the name.

     There are other issues to determining who is running the
program in non-setuid environments but that can be covered some
other time.

     Steve

Traditional disclaimer: I welcome non-malicious flames from
wizards on bugs in the above.
-- 
Life : Stephen J. Friedl @ V-Systems, Inc./Santa Ana, CA   *Hi Mom*
CSNet: friedl%vsi.uucp@kent.edu  ARPA: friedl%vsi.uucp@uunet.uu.net
uucp : {kentvax, uunet, attmail, ihnp4!amdcad!uport}!vsi!friedl

blarson@skat.usc.edu (Bob Larson) (03/14/88)

In article <700@virginia.acc.virginia.edu> scl@virginia.acc.Virginia.EDU (Steve Losen) writes:
>2)  Avoid setuid if you can.  I once wrote a very simple print spooler
>	that puts files in a directory where they are picked up periodically
>	by a daemon to be printed.  I made the directory 777 instead of using
>	setuid-to-lp fraud.  Sure a malicious user can remove files in the
>	print queue. So what?

So what?  It depends a lot on what you are printing.  When someone
modifies the batch of checks waiting to be printed or gives the
confedintial information you were printing to a compeditor I doubt
your boss wold say "So what?".
-- 
Bob Larson	Arpa: Blarson@Ecla.Usc.Edu	blarson@skat.usc.edu
Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson
Prime mailing list:	info-prime-request%fns1@ecla.usc.edu
			oberon!fns1!info-prime-request

jbs@fenchurch.MIT.EDU (Jeff Siegal) (03/14/88)

In article <7616@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes:
>In article <700@virginia.acc.virginia.edu> scl@virginia.acc.Virginia.EDU (Steve Losen) writes:
>>	[...].  I made the directory 777 instead of using
>>	setuid-to-lp fraud.  Sure a malicious user can remove files in the
>>	print queue. So what?
>So what?  It depends a lot on what you are printing.  When someone
>modifies the batch of checks waiting to be printed or gives the
>confedintial information you were printing to a compeditor I doubt
>your boss wold say "So what?".

Setting the directory mode to 777 by itself doesn't let anyone modify
or read anything.  All it allows people do is:

	1. List the file names in the directory
	2. Access files in the dirctory _according_to_their_modes.
	3. Remove files from the directory.

#1 can be prevented, if necessary by setting the directory mode to 733
rather than 777.  This effectively prevents #2 and #3 if you use
obscure file names.  #2 can be absolutely prevented in any case by
setting the mode of each file in the directory appropriately.  #3 can
be absolutely prevented on BSD 4.3 systems by setting the sticky bit
(mode 1733) on the directory.

The security risk is minimal, since all that can be done is removing
the files, not reading or writing them. Even this can be effectively
prevented by using the messures described above.

Jeff Siegal

wesommer@athena.mit.edu (William Sommerfeld) (03/14/88)

In article <8468@eddie.MIT.EDU> jbs@eddie.MIT.EDU (Jeff Siegal) writes:
>#1 [listing the directory] can be prevented, if necessary by setting the
>directory mode to 733 rather than 777.  This effectively prevents
>#2 [reading and/or writing files in the directory] and #3 [deleteing
>files] if you use obscure file names.  #2 can be absolutely prevented
>in any case by setting the mode of each file in the directory
>appropriately.  #3 can be absolutely prevented on BSD 4.3 systems by
>setting the sticky bit (mode 1733) on the directory.

Of course, this implies that the daemon which reads this queue runs as
root, which may not be desirable either.

Secure systems should be able to withstand attacks when the attackers
have complete access to all design documentation, source, and object
code.  "Security through obscurity" is not security at all.

 - How do you seed the random number generator used to generate the
100-character `obscure' filename such that knowing, for example, the
approximate starting time and process ID of a process which dropped
something interesting in the queue doesn't make things any easier.

A much better approach would be to have a pseudo-user for for whatever
facility you were creating, and a _short_, _auditable_ setuid program,
without shell escapes and other similar nonsense, to deposit things in
the spool directory.  If you need to put a fancy user-interface on it,
build the user interface as a separate process and have it fire up a
setuid backend process to do the `real work'.

					- Bill

friedl@vsi.UUCP (Stephen J. Friedl) (03/14/88)

In article <8468@eddie.MIT.EDU>, jbs@fenchurch.MIT.EDU (Jeff Siegal) writes:
> Setting the directory mode to 777 by itself doesn't let anyone modify
> or read anything.  All it allows people do is:
> 
> 	1. List the file names in the directory
> 	2. Access files in the dirctory _according_to_their_modes.
> 	3. Remove files from the directory.

You missed at least two:

	4. Rename files
	5. Add new files

What if you see a job ready to print.  You know payroll will be printing
checks soon so you make up a file of your own checks.  When you see it
in the queue you remove theirs and insert yours.

Another one: your system's laser printer has usage accounting built
into the spooler.  You make up your own spooler files and stick them
in the directory directly.  The despooler never knows the difference.

The set-sticky-bit-on-directory fix will be available for SVR3.2
from AT&T soon.  If this is done, you only can only unlink files
if you own the file or own the directory.  This largely fixes the
above problems in the manner of BSD.

-- 
Steve Friedl, KA8CMY      ARPA/CSNet:  friedl@vsi.uu.net       *Hi Mom*
uucp email : { kentvax, uunet, attmail, ihnp4!amdcad!uport }!vsi!friedl
"Too bad we judge others by their actions and ourselves by our motives"

davidsen@steinmetz.steinmetz.UUCP (William E. Davidsen Jr) (03/15/88)

In article <700@virginia.acc.virginia.edu> scl@virginia.acc.Virginia.EDU (Steve Losen) writes:
| 
| 2)  Avoid setuid if you can.  I once wrote a very simple print spooler
| 	that puts files in a directory where they are picked up periodically
| 	by a daemon to be printed.  I made the directory 777 instead of using
| 	setuid-to-lp fraud.  Sure a malicious user can remove files in the
| 	print queue. So what?  To my knowlege, no one has ever done that in
| 	the two years since I put the system up.  Ask yourself, "Does this
| 	really need to be setuid?"  For example, I would *never* make a program
| 	setuid just so it could write to a protected logfile.  To hell with it.
| 	make the logfile 622.
  While I agree with much of what you said, I totally disagree on this
point. I can't belive that this is workable of any system available to
hackers (ie. public access, campus machines, etc), and would not really
provide benefits on even a machine loaded with well behaved users.

  While setuid leaves problems, I doubt the proper way to solve them is
to let people do things with system queues without using setuid. I have
spent a great deal of time setting my system so that it is secure (one
of the systems is public access). Here are a few things I've done:

  Scan the entire filesystems with find and identify every program in
the system with setuid on. Any of these which are owned by system uids
are examined carefully for problems.

  I have all my system queues set to require access via setuid, just the
opposite of your method. I have all my lp and uucp stuff locked up,
accessed by a small number of trusted programs. Other programs which
access the queues may be setuid, but are not executable by anyone but
the user and root. When creating files setuid prevents files from having
dubious ownership, such as root. If you leave a file owned by root, it
can be modified.

  I have logins just for working on various subsystems, most commonly
uumaint (uucp) and lpmaint (lp). Logins which access uucico run under
another uid, not uucp. All files and queues are accessable by uucp
(unless other access is needed). No program which does a "system" call
or starts a shell in any way is setuid.

  I have accounting on, running to a write only device. This allows me
to analize system behavior as needed. It has helped me spot and correct
problems, and is checked by a cron script daily and by me when I get a
bad feeling.

  I don't allow users to execute many of the uucp programs, particularly
uucico. I'm not going to post the hole here, but only logins can run the
program on my system.

  I hope that this offers another viewpoint on this area.
-- 
	bill davidsen		(wedu@ge-crd.arpa)
  {uunet | philabs | seismo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

scl@virginia.acc.virginia.edu (Steve Losen) (03/15/88)

In article <391@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes:
>In article <8468@eddie.MIT.EDU>, jbs@fenchurch.MIT.EDU (Jeff Siegal) writes:
>> Setting the directory mode to 777 by itself doesn't let anyone modify
>> or read anything.  All it allows people do is:
>> 
>> 	1. List the file names in the directory
>> 	2. Access files in the dirctory _according_to_their_modes.
>> 	3. Remove files from the directory.
>
>You missed at least two:
>
>	4. Rename files
>	5. Add new files
>
>What if you see a job ready to print.  You know payroll will be printing
>checks soon so you make up a file of your own checks.  When you see it
>in the queue you remove theirs and insert yours.

Sorry I started such  a  controversy  here.  I  must  agree  that  in  many
situations  you  need  a  secure  print  spooler.  My  intent was to simply
illustrate  that  in  some  situations  setuid  hassles  can   be   avoided
altogether.  One should always balance the risks of opening up permisssions
on certain files/directories with  the  possibly  hidden  risks  of  poorly
designed setuid software.

For  the  record,  the  spooler  I wrote was a shell script and we all know
setuid shell scripts are either  unsupported  (sysV)  or  a  security  hole
(BSD).  This  script  emulates  a  "spool"  command  that runs on our Prime
systems that can print to sites all over the grounds (campus). The  spooler
shell  script  puts files in a directory for a daemon to kermit (ugh!) to a
Prime system for printing. The users of this system are all academic  types
who  understand the risks, drawbacks (slowness), etc., but who nevertheless
have successfully and happily printed their jobs with  this  Rube  Goldberg
monstrosity for the past two years.

I  admit  that  this  system  was  cobbled  up  quite  hastily, but we were
expecting to get TCP/IP on the Primes real soon and well, uh, ... you  know
how these things go.
-- 
Steve Losen     scl@virginia.edu
University of Virginia Academic Computing Center

hansen@pegasus.UUCP (Tony L. Hansen) (03/16/88)

<	3. Remove files from the directory.
<
< #3 can be absolutely prevented on BSD 4.3 systems by setting the sticky
< bit (mode 1733) on the directory.

This enhancement was also put into System V release 3.2. Also, the /tmp and
/usr/tmp directories are shipped as mode 1777. This was just one of the
modifications made in that release to make the UNIX System more secure.

					Tony Hansen
				ihnp4!pegasus!hansen, attmail!tony

nevin1@ihlpf.ATT.COM (00704a-Liber) (03/16/88)

In article <700@virginia.acc.virginia.edu> scl@virginia.acc.Virginia.EDU (Steve Losen) writes:
>I have no guide for writing setuid programs, but here are a few
>ideas that come to mind:
>
>[All sorts of good setuid precautions]

Most of the programs that non-SA's write that use setuid could just as easily
use setgid with a unique gid for all the files that need to be affected.  For
example:  I recently wrote a utility that needed to log user's requests.  I
created a group (let's call it SGROUP) different than my default group, did a
'chgrp SGROUP utility', 'chmod 2711 utility' (setgid bit), 'chgrp SGROUP
directory', 'chmod 770 directory', 'chgrp SGROUP logfile', and 'chmod 660
logfile' (you do need to create the logfile yourself; otherwise, you won't own
it).  This, along with the other precautions mentioned in the previous article,
should be sufficient for many programs which require access to files which are
not owned.

One more thing:  NEVER HAVE THE SETUID (SETGID) BIT SET ON A FILE WHICH THE
WORLD HAS WRITE PRIVILEGES ON!!!  On many systems writing to a file does not
turn off the setuid/setgid bit; if you let the world write to this file, you
are just waiting for a disaster to happen!!

Hope this helps,
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

jack@cwi.nl (Jack Jansen) (03/17/88)

Well, some things I check a set-uid program for (most of them
learned in the time I wasn't interested yet in writing secure
setuid program but in find bugs in setuid programs:-)

- Never take for granted that the user will not do this-or-that. She
  will.
- Check, double-check and triple-check *each* library or system
  call. Try to think of devious ways of making it do things it
  shouldn't. Hints: think of IFS, links, symbolic links, running
  in removed directories(!), environment variables in general,
  job control, etc etc etc.
- Never take for granted that the user will not do this-or-that. He
  will.
- Always be aware of the time-sharing aspect of unix. Never write
  code like
  if( stat(file, &sb) < 0 ) {
      /* Now we're sure the file doesn't exist so it'll be owned
      ** by us.
      */
      fd = creat(file, mode);
  }
- Never take for granted that the user will not do this-or-that. She
  will.
- Never think that setgid or setuid to bin is less dangerous than
  setuid to root.
- Never take for granted that the user will not do this-or-that. He
  will.
- Never allow interrupt routines, *not even with a signal catcher*
  to clean up in a critical section. 'ulimit stacksize' can be
  very useful at times..........
- The difficult one: never trust any other machine. Given control
  over one machine on an ethernet, for instance, I can impersonate
  *any* other machine by first crashing the original, trusted, machine
  and then impersonating it.

And, of course, the general rule is not to write setuid programs
in the first place, but that has been handled by other people.
-- 
	Jack Jansen, jack@cwi.nl (or jack@mcvax.uucp)
	The shell is my oyster.

jc@heart-of-gold (John M Chambers x7780 1E342) (03/18/88)

> And, of course, the general rule is not to write setuid programs
> in the first place, but that has been handled by other people.

One question I have:  To my knowledge, there does not actually exist a way
to "write a setuid program".

Yes, of course, I know how to type:
	chmod 6755 foo
I claim that this does not constitute "writing a setuid program".  What it
does is take an existing non-setuid program (that is already written and
compiled) and make it into a setuid program.  But when the programmer wrote
it, it wasn't setuid.

Lest people think I am being facetious, I'd like to point out that there
is an important point at work here.  When writing a program, I don't know
whether it will be setuid.  So how can I follow the above advice? (Obviously, 
by not writing any programs! :-)  When I write a line of code, how do I 
determine whether it is in a setuid program?

There is one sense in which I could conceive of actually writing a setuid
program.  If there were a way to test at run time whether the program (well,
actually the process, but you know what I mean) is setuid:

	if (setuid(getpid())) {
		<<Don't do a bunch of stuff>>
	} else {
		<<Go ahead and do them>>
	}

Can anyone show me the source for setuid()?  I suspect that you can't,
but I'd like someone to explain how stupid I'm being and how easy it is.

For a further argument, consider the alternative:

	#if SETUID
		<<Don't do a bunch of stuff>>
	#else
		<<Go ahead and do them>>
	#endif

I contend that there is no way for the C preprocessor to correctly 
implement the above #if command.  I'd be very interested in being
proved incorrect.

matt@oddjob.UChicago.EDU (Schizophrenic Solipsist) (03/18/88)

jc@heart-of-gold (John M Chambers x7780 1E342) asks:

)   If there were a way to test at run time whether the program (well,
) actually the process, but you know what I mean) is setuid:
) 
) 	if (setuid(getpid())) {
) 		<<Don't do a bunch of stuff>>
) 	} else {
) 		<<Go ahead and do them>>
) 	}
) 
) Can anyone show me the source for setuid()?  I suspect that you can't,
) but I'd like someone to explain how stupid I'm being and how easy it is.

int
i_am_setuid()
{
	return getuid() != geteuid();
}

/* I *think* it is done in SysV as it is in BSD.  Amen. */
________________________________________________________
Matt	     University		matt@oddjob.uchicago.edu
Crawford     of Chicago     {astrovax,ihnp4}!oddjob!matt

geoff@desint.UUCP (Geoff Kuenning) (03/18/88)

In article <8468@eddie.MIT.EDU> jbs@eddie.MIT.EDU (Jeff Siegal) writes:

> Setting the directory mode to 777 by itself doesn't let anyone modify
> or read anything.  All it allows people do is:
> 
> 	1. List the file names in the directory
> 	2. Access files in the dirctory _according_to_their_modes.
> 	3. Remove files from the directory.

You forgot one:

	4. Create files in the directory.

In practice, this allows modifying, though not reading, any file.  Simply
remove the original and replace it by your favorite Trojan horse.  On
System V (the system under discussion), you can even give the file away
to the original owner and group.  With the utime(2) call, you can even
put in the original access and modification (though not i-node change)
times.
-- 
	Geoff Kuenning   geoff@ITcorp.com   {uunet,trwrb}!desint!geoff

pdb@sei.cmu.edu (Patrick Barron) (03/19/88)

In article <127@heart-of-gold> jc@heart-of-gold (John M Chambers x7780 1E342) writes:
>Lest people think I am being facetious, I'd like to point out that there
>is an important point at work here.  When writing a program, I don't know
>whether it will be setuid.  So how can I follow the above advice? (Obviously, 
>by not writing any programs! :-)  When I write a line of code, how do I 
>determine whether it is in a setuid program?

   On the contrary, normally when one writes a program that is going to
have the set-uid bit set, one knows that for a fact before starting.  Taking
random programs that you know little or nothing about, and making them
set-uid, is an exceptionally bad idea.

>Can anyone show me the source for setuid()?  I suspect that you can't,

  No, I can't show you the source for setuid(), but only because my Ultrix
license agreement prohibits it.... :-)  Seriously, there really is a setuid()
system call.  It doesn't do what you want, though.

--Pat.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/20/88)

In article <3098@pegasus.UUCP> hansen@pegasus.UUCP (XT1554000-Tony L. Hansen;LZ 3B-315;6243) writes:
>This enhancement was also put into System V release 3.2. Also, the /tmp and
>/usr/tmp directories are shipped as mode 1777. This was just one of the
>modifications made in that release to make the UNIX System more secure.

How well does this work in practice?  Due to the large number of
utilities that fail to properly clean up their tmp files, often
the system administrator ends up having to periodically clean out
/tmp and /usr/tmp.  With this new scheme, he'll have to become
superuser to do this, unless a privileged operator-executable
cleanup utility is provided (or the system is rebooted and does
this on each reboot).

gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/20/88)

In article <127@heart-of-gold> jc@heart-of-gold (John M Chambers x7780 1E342) writes:
-> And, of course, the general rule is not to write setuid programs
-> in the first place, but that has been handled by other people.
-One question I have:  To my knowledge, there does not actually exist a way
-to "write a setuid program".

That phrase is just shorthand for "write a program that will have
to have the resulting binary made set-UID to do its job properly".

jc@minya.UUCP (John Chambers) (03/21/88)

> A much better approach would be to have a pseudo-user for for whatever
> facility you were creating, and a _short_, _auditable_ setuid program,
> without shell escapes and other similar nonsense, to deposit things in
> the spool directory.  

A program that does exactly this was posted to one of the sources group
a couple of years back, under the name "append.c".  Perhaps it's time
to post it again.  Or is it archived in one or the source newsgroups?

It was also a Unix implementation of a Multics security feature.  It's
also a good counter-example to the frequent claims that all setuid programs
are Bad Things.

-- 
John Chambers <{adelie,ima,maynard,mit-eddie}!minya!{jc,root}> (617/484-6393)

terry@wsccs.UUCP (terry) (03/22/88)

In article <386@vsi.UUCP>, friedl@vsi.UUCP (Stephen J. Friedl) writes:
> setuid and setgid programs should be mode --x--x--x so people
> like me :-) can't look at them.  When digging for holes on a
> machine the first thing I do is run strings on the set[ug]id
> programs to look for the standard holes -- you can recognize them
> after a while.

	That's totally useless on machines where you have to load a software
emulator to run a program (say 286 programs on uPort 386).  In addition, a
smart programmer will use 'strip' on his programs.

	Besides why do that to look for holes?  There are plenty of other
nifty possibilities for holes:

	1) if /usr/spool/mail is writeable and on the same device as /etc:

		$ ln /etc/passwd /usr/spool/mail/fred
		$ echo "sneak::0:1:A hacker:/:/bin/sh" | mail fred
		$ su fred
		#

	2) if you were working on a VM system, you could debug SU.  The system
	   would mark the page you are working on as "in use";  change it so
	   you don't have to enter a password.  Go to another terminal.
	   Log in.  su.  Since the page is marked as in core, even if it has
	   been modified, it isn't reloaded from the disk, and your patched
	   version will be loaded and you will be signed on as root.

	3) On older system III systems, length-checking wasn't done on the
	   password field, and the compare buffer was pre-loaded and right
	   after the input buffer.  If you typed 88 of anything, you were in.

	While it's true that these will only work on badly ported or badly
administered systems, they seem (at least to me) to be more of a problem than
SIUD root programs.  2 and 3 have been fixed.  1 is the fault of incompetent
administration.

	It's true that you should be careful of SUID programs, but not any
more so than you should be careful of ANY permission changes or anything else
you do as root.  There are no more problems with security on UNIX than there
are on any other multi-user system; less, in a lot of cases.  If someone
really wanted your data, they'd break into your office if no other method was
available.


| Terry Lambert           UUCP: ...{ decvax, ihnp4 }                          |
| @ Century Software          : ...utah-cs!uplherc!sp7040!obie!wsccs!terry    |
| SLC, Utah                                                                   |
|                   These opinions are not my companies, but if you find them |
|                   useful, send a $20.00 donation to Brisbane Australia...   |
| 'There are monkey boys in the facility.  Do not be alarmed; you are secure' |

friedl@vsi.UUCP (Stephen J. Friedl) (03/25/88)

In article <347@wsccs.UUCP>, terry@wsccs.UUCP (terry) writes:
< In article <386@vsi.UUCP>, friedl@vsi.UUCP (Stephen J. Friedl) writes:
< > setuid and setgid programs should be mode --x--x--x so people
< > like me :-) can't look at them.  When digging for holes on a
< > machine the first thing I do is run strings on the set[ug]id
< > programs to look for the standard holes -- you can recognize them
< > after a while.
< 
< 	That's totally useless on machines where you have to load a software
< emulator to run a program (say 286 programs on uPort 386).  In addition, a
< smart programmer will use 'strip' on his programs.
< 
< 	Besides why do that to look for holes?  There are plenty of other
< nifty possibilities for holes: [relevent security holes presented here]
<
< 	It's true that you should be careful of SUID programs, but not any
< more so than you should be careful of ANY permission changes or anything else
< you do as root.  There are no more problems with security on UNIX than there
< are on any other multi-user system; less, in a lot of cases.  If someone
< really wanted your data, they'd break into your office if no other method was
< available.

Yes, you present some other holes that can be found on many Unix
machines, I've used most of them myself.  However, just because
you are more clever than me does not mean that advice on --s--s--x
is totally bogus.  While it may not work for emulators, I
suspect that this is not the most widespread case and that a
readable file is indeed an invitation to scam.  Stripping the
symbols from a file does not remove the strings from a file, and
programmers clever enough to hide the strings are likely clever
enough to write the program properly in the first place.

--s--s--x will keep some people out.  It may not keep you out and
it may not keep me out and it may not keep Chris Torek (hi
Chris!) out but it will keep *some* people out.  It was not
advertised as the final solution to system security, and shooting
holes in it to show how clever you are serves only yourself.
Again:  surely you can find more pleasant/constructive ways of
putting in your two cents worth.  Why must you be so combative?

     Steve
-- 
Steve Friedl      V-Systems, Inc.        *Hi Mom*
friedl@vsi.com   {uunet,attmail,ihnp4}!vsi!friedl

cudcv@daisy.warwick.ac.uk (Rob McMahon) (03/27/88)

In article <8468@eddie.MIT.EDU> jbs@eddie.MIT.EDU (Jeff Siegal) writes:
|In article <7616@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes:
|>about setuid lp programs.
|Setting the directory mode to 777 by itself doesn't let anyone modify
|or read anything.  All it allows people do is:
|
|	1. List the file names in the directory
|	2. Access files in the dirctory _according_to_their_modes.
|	3. Remove files from the directory.

	4. Add files (or links) to the directory.

If you're not careful Joe User can get files printed out which he has no
read permission to by making links, symbolic links, into this directory.

Rob
-- 
UUCP:   ...!mcvax!ukc!warwick!cudcv	PHONE:  +44 203 523037
JANET:  cudcv@uk.ac.warwick.cu          ARPA:   cudcv@cu.warwick.ac.uk
Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England

stevec@fornax.UUCP (Steve Cumming) (03/29/88)

In article <347@wsccs.UUCP>, terry@wsccs.UUCP (terry) writes:
>
>	[ remarks on previous articles suppressed]
> 
> 	1) if /usr/spool/mail is writeable and on the same device as /etc:
> 
> 		$ ln /etc/passwd /usr/spool/mail/fred
> 		$ echo "sneak::0:1:A hacker:/:/bin/sh" | mail fred
> 		$ su fred
> 		#

I tried this out on a Sun running 3.4. It don't work. 
Mail is evidently smart enough to check for the existence of 
the addressee, either locally or through the Yellow Pages.

I don't see as it matters whether /etc/passwd and the mail
directory are on the same file system.

Moreover, if mail doesn't run setuid, which on our site it doesn't,
then it has no special priveleges, and can't write to a soft or
hard link to a protected file.

Steve Cumming
Systems worker
School of Computing Science
SFU

ubc-vision!fornax!stevec

jgy@hropus.UUCP (John Young) (03/30/88)

> In article <347@wsccs.UUCP>, terry@wsccs.UUCP (terry) writes:
> >
> >	[ remarks on previous articles suppressed]
> > 
> > 	1) if /usr/spool/mail is writeable and on the same device as /etc:
> > 
> > 		$ ln /etc/passwd /usr/spool/mail/fred
> > 		$ echo "sneak::0:1:A hacker:/:/bin/sh" | mail fred
> > 		$ su fred
> > 		#
> 
> I tried this out on a Sun running 3.4. It don't work. 
> Mail is evidently smart enough to check for the existence of 
> the addressee, either locally or through the Yellow Pages.
> 
> I don't see as it matters whether /etc/passwd and the mail
> directory are on the same file system.
> 

OK.  Just take a look at the crontabs entries, /etc/rc entries,
/etc/backup_stuff entries and so on and so on (temp files for
ps, sar, etc....) for any refrences to files in /tmp or /usr/tmp.
Link the /etc/passwd file to that /tmp/file and either run the
command or wait for cron/root to run it for you!  BANG there goes
the password file!  If you pick the right utility, it will change
the modes so you can make your own entries.
SYSV's sticky directory bit's will do nothing for this.

The answer,  keep the /etc on a filesystem which does not need
contain directories writeable by "normal"(abnormal?) users.
Ideally, of course the whole root fs would be write protected
while in multi-user.

madd@bu-cs.BU.EDU (Jim Frost) (03/31/88)

In article <469@fornax.UUCP> stevec@fornax.UUCP (Steve Cumming) writes:
>In article <347@wsccs.UUCP>, terry@wsccs.UUCP (terry) writes:
>> 
>> 	1) if /usr/spool/mail is writeable and on the same device as /etc:
>> 
>> 		$ ln /etc/passwd /usr/spool/mail/fred
>> 		$ echo "sneak::0:1:A hacker:/:/bin/sh" | mail fred
>> 		$ su fred
>> 		#
>
>I tried this out on a Sun running 3.4. It don't work. 
>Mail is evidently smart enough to check for the existence of 
>the addressee, either locally or through the Yellow Pages.

Don't forget that a Sun uses a slightly different environment than
straight UNIX.  Also, user "fred" should be the person who's trying to
do this.  He'll have an /etc/passwd entry.

>I don't see as it matters whether /etc/passwd and the mail
>directory are on the same file system.

He requires two things -- /usr/spool/mail must be writable (usually it
isn't) so that you can create a file (ie /usr/spool/mail/fred) which
is a hard link to /etc/passwd.  They must be on the same file system
because cross-device hard links aren't possible, which is the second
requirement.

Obviously sendmail must be able to write /etc/passwd for this to work.
For many systems, it may well be able to.  Machines which use the smtp
service (tcp port 25, at least on this system) must have sendmail
running root or they will be unable to access the port (as it's <
1024).

This technique won't work on a lot of systems, but I'd suspect that it
would work on many of the smaller ones (the ones with little disk
space and untrained sysadmins, mostly).  Some flaws in this system
include:

	* some systems use a hash table created by vipw to maintain
	  fast /etc/passwd lookups.  If you try this and the system
	  uses a hash table, you're going to get killed the next time
	  the administrator looks at the passwd file, since it'll have
	  your name in it from the mail header.  You won't be able to
	  su because the hash table won't be updated.  You can't
	  update it because you're not root and can't run vipw.  Too
	  bad.
	* some systems don't use /etc/passwd for the real password
	  file.  Sun yellowpages is an example, although /etc/passwd
	  is used locally to that machine.
	* most systems don't put /etc/passwd and /usr/spool/mail on
	  the same device.
	* most systems don't have a public-writable /usr/spool/mail.

All you'd have to do to defend against this method is make
/usr/spool/mail non-publicly writable, which it should be anyway.

Another example of how "innocent" things like links can be used
against you....

jim frost
madd@bu-it.bu.edu