Path: utzoo!mnetor!uunet!vsi!friedl From: friedl@vsi.UUCP (Stephen J. Friedl) Newsgroups: comp.unix.wizards Subject: Re: Guide to writing secure setuid programs? Message-ID: <386@vsi.UUCP> Date: 13 Mar 88 05:02:45 GMT References: <181@wsccs.UUCP> <722@rivm05.UUCP> <1037@woton.UUCP> Organization: V-Systems, Inc. -- Santa Ana, CA Lines: 60 Summary: a couple more rules for setuid/setgid 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