Guide to writing secure setuid programs?

Stephen J. Friedl friedl at vsi.UUCP
Sun Mar 13 15:02:45 AEST 1988


In article <1037 at woton.UUCP>, riddle at 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 at kent.edu  ARPA: friedl%vsi.uucp at uunet.uu.net
uucp : {kentvax, uunet, attmail, ihnp4!amdcad!uport}!vsi!friedl



More information about the Comp.unix.wizards mailing list