ccdn@levels.sait.edu.au (DAVID NEWALL) (05/31/89)
According to the manual, cuserid(3) is supposed to "return the character login name of the user". I interpret this as meaning it will return the login name of the invoker. This is _not_ what cuserid() does. In fact, cuserid() returns the login name of the person who is logged in on the terminal pointed to by stdin, stdout or stderr. So if one were to close stdin (or point it at a text file), close stderr, and point stdout at someone else's terminal, cuserid() would return that person's login name, and not yours. A great pity if the program you're running relies on cuserid() to identify the caller. Oh, and the same applies for getlogin(). So people, do not, absolutely do not, rely on these functions to identify the user. Use getuid() or geteuid() instead. I personally think this is an important security hole. Consider, for example, set gid mail programs... David Newall Phone: +61 8 343 3160 Unix Systems Programmer Fax: +61 8 349 6939 Academic Computing Service E-mail: ccdn@levels.sait.oz.au SA Institute of Technology Post: The Levels, South Australia, 5095
friedl@vsi.COM (Stephen J. Friedl) (05/31/89)
In article <289@levels.sait.edu.au>, ccdn@levels.sait.edu.au (DAVID NEWALL) writes: > According to the manual, cuserid(3) is supposed to "return the character > login name of the user". I interpret this as meaning it will return the > login name of the invoker. This is _not_ what cuserid() does. > [...] > So people, do not, absolutely do not, rely on these functions to identify > the user. Use getuid() or geteuid() instead. Here is an alternate method that may be a little bit more flexible (for Sys V, at least). First get the $LOGNAME environment variable and look up the password entry for it. If the uid here matches getuid (or geteuid, depending on your application), go ahead and believe $LOGNAME. If it doesn't match, forgery is going on and you have to use the getuid entry. This technique allows multiple accounts sharing the same uid to distinguish between them. Presumably, the accounts only share if fraud between them is not a big deal. Steve -- Stephen J. Friedl / V-Systems, Inc. / Santa Ana, CA / +1 714 545 6442 3B2-kind-of-guy / friedl@vsi.com / {attmail, uunet, etc}!vsi!friedl You can't have everything: where you would put it?
guy@auspex.auspex.com (Guy Harris) (06/01/89)
>According to the manual, cuserid(3) is supposed to "return the character >login name of the user". I interpret this as meaning it will return the >login name of the invoker. This is _not_ what cuserid() does. Which manual is "the manual"? The S5R3 manual page says it returns "a character-string representation of the login name that the user of the current process is logged in under", which makes it not surprising that, as you note: >In fact, cuserid() returns the login name of the person who is logged in >on the terminal pointed to by stdin, stdout or stderr. >Oh, and the same applies for getlogin(). In fact, "cuserid" in AT&T's implementation just tries to do a "getlogin" first and, if that fails, uses "getpwuid(getuid())". I assume any Berkeley implementations do the same.... >So people, do not, absolutely do not, rely on these functions to identify >the user. Use getuid() or geteuid() instead. Yup. In most versions of UNIX, there is *no* guaranteed way to get the login name for the current session, since doing so basically involves 1) getting the tty name for the current session and 2) finding the "utmp" entry for that session, and 1) can only be done if you have a handle on that tty, and as you note there's no way of reliably getting such a handle (no, "/dev/tty" doesn't do so - an "fstat" on it will, in all UNIXes with which I'm familiar, report the major and minor device number of "/dev/tty", and thus doesn't give you enough information to find the device in "/dev" to which it refers). I think some versions may actually stash the login name in the U area with a privileged call, and provide a call to fetch it. (I think PWB/UNIX 1.0 did this; I seem to remember something in the V9 manual that indicated that there might be such a call there.) It is worth noting that, in some cases, you may *want* the answer that "getpwuid(getuid())" or "getpwuid(geteuid())" gives you, and not the answer that even an "unbreakable" "getlogin()" would give you....
ccdn@levels.sait.edu.au (DAVID NEWALL) (06/02/89)
In article <1725@auspex.auspex.com>, guy@auspex.auspex.com (Guy Harris) writes: > Which manual is "the manual"? The S5R3 manual page says it returns "a > character-string representation of the login name that the user of the > current process is logged in under", which makes it not surprising that, > as you note: > >>In fact, cuserid() returns the login name of the person who is logged in >>on the terminal pointed to by stdin, stdout or stderr. Huh? I don't get it. If I close stdin and stderr, and point stdout at your terminal, then cuserid() will say that I am you. That's isn't a "representation of the login name that the user of the current process is logged in under". And that's why I was surprised. (Though on reflection, I am now not surprised, given how it must surely work -- scanning the utmp file). David Newall Phone: +61 8 343 3160 Unix Systems Programmer Fax: +61 8 349 6939 Academic Computing Service E-mail: ccdn@levels.sait.oz.au SA Institute of Technology Post: The Levels, South Australia, 5095
wagoner@imokay.dec.com (Darryl Wagoner) (06/02/89)
Neither cuserid(3) or getlogin(3) in Ultrix checks stdin for user information. The cuserid(3) routine tries to do a getlogin(3); if it fails, it then does a getpwuid(3) of the real uid. The getlogin(3) routine only gets login information from utmp. I have never checked this on other systems, but would be interested in knowing if this is indeed a bug on other versions of Unix. -- Darryl Wagoner wagoner@imokay.dec.com Digital (work) 508.264.5586 Secure Workstation Project (DTN) 293.5586 Boxboro, Ma.
karl@haddock.ima.isc.com (Karl Heuer) (06/03/89)
The plot thickens. In POSIX, cuserid() is required to use the *effective uid* of the process. The Rationale section does not comment on this inconsistency with traditional implementations. Moreover, POSIX getlogin() is supposed to return the login name associated with the *controlling terminal*, not the tty on descriptor 0-2 as is commonly implemented. Since, as Guy points out, a program can't always find the true name of its controlling terminal, it would seem that this requires either a new system call, or else getlogin() should just give up and return NULL. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
wagner@humboldt.uucp (Juergen Wagner) (06/03/89)
Cuserid is *NOT* a security hole. Programs relying on a property of this function which it doesn't have, are security holes. Juergen Wagner gandalf@csli.stanford.edu wagner@arisia.xerox.com
sms@WLV.IMSD.CONTEL.COM (Steven M. Schultz(Y)) (06/03/89)
In article <902@arisia.Xerox.COM> wagner@arisia.xerox.com (Juergen Wagner) writes: >Cuserid is *NOT* a security hole. Programs relying on a property of this >function which it doesn't have, are security holes. >Juergen Wagner gandalf@csli.stanford.edu > wagner@arisia.xerox.com Enough is enough! After seeing this "problem/bug" posted umpteen times i no longer restrain myself... cuserid() is a System V(anilla) construct/problem NOT a 2.10.1BSD (or for that matter a 4.3BSD) concern at all. for real 2BSD bugs contact either Keith Bostic (bostic@okeeffe.berkeley.edu) (who will probably refer you to me) or Steven Schultz (sms@wlv.imsd.contel.com). Steven M. Schultz sms@wlv.imsd.contel.com
guy@auspex.auspex.com (Guy Harris) (06/08/89)
>Neither cuserid(3) or getlogin(3) in Ultrix checks stdin for user >information. Neither of them "check stdin for user information", in the sense of reading said information from standard input, on *any* system I know of. *However*: >The cuserid(3) routine tries to do a getlogin(3); if it fails, it then does a >getpwuid(3) of the real uid. > >The getlogin(3) routine only gets login information from utmp. But on the versions of UNIX with which I'm familiar, in order to find the entry in "/etc/utmp" it has to figure out which terminal the job is running from, and it does that by calling "ttyslot", which finds that out by calling "ttyname" on file descriptors 0, 1, and 2, successively, until it gets a non-null pointer back. In other words, it assumes that one of those three file descriptors is opened to the terminal in question; since it checks standard input first, you can just redirect standard input to some other terminal and *voila*, it checks the "utmp" entry for *that* terminal, instead. >I have never checked this on other systems, but would be interested in knowing >if this is indeed a bug on other versions of Unix. If you consider it a bug to be able to redirect standard input and, as a result, be able to force "getlogin" give you the wrong information, you might find it is a bug in many versions of UNIX, *including* Ultrix.... I think it may not be a bug in some versions, because they have a "getlogin" that's implemented as a system call.
rob@PacBell.COM (Rob Bernardo) (06/08/89)
In article <1768@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
+If you consider it a bug to be able to redirect standard input and, as a
+result, be able to force "getlogin" give you the wrong information, you
+might find it is a bug in many versions of UNIX, *including* Ultrix....
The "problem" is that a programmer might use cuserid() without knowing
about this "deception".
This might be particularly bad in, say, a mail user agent. MUA's often
must run setgid. As a setgid program is has access to *anyone's*
incoming mail box, and must judge whether the user would normally be
able to access the mailbox s/he has directed the MUA to access. If
cuserid() is used to determine the user's id, the MUA may unwittingly
grant access to some other person's incoming mailbox.
--
Rob Bernardo, Pacific Bell UNIX/C Reusable Code Library
Email: ...![backbone]!pacbell!pbhyf!rob OR rob@pbhyf.PacBell.COM
Office: (415) 823-2417 Room 4E850O San Ramon Valley Administrative Center
Residence: (415) 827-4301 R Bar JB, Concord, California
leo@philmds.UUCP (Leo de Wit) (06/08/89)
In article <472@imokay.dec.com> wagoner@imokay.dec.com (Darryl Wagoner) writes: |Neither cuserid(3) or getlogin(3) in Ultrix checks stdin for user |information. | |The cuserid(3) routine tries to do a getlogin(3); if it fails, it then does a |getpwuid(3) of the real uid. | |The getlogin(3) routine only gets login information from utmp. | |I have never checked this on other systems, but would be interested in knowing |if this is indeed a bug on other versions of Unix. On Ultrix, having read about the potential security problems with getlogin(), it took me about 5 minutes to break a privilized setuid program (read: become root) that relied upon getlogin() ... with a shell script! Leo.
C.R.Ritson@newcastle.ac.uk (Chris Ritson) (06/08/89)
In article <472@imokay.dec.com> wagoner@imokay.dec.com (Darryl Wagoner) writes: >The getlogin(3) routine only gets login information from utmp. > >I have never checked this on other systems, but would be interested in knowing >if this is indeed a bug on other versions of Unix. I am working on an Encore multimax, and have access to a BSD4.3 source for a VAX. As I understand it, getlogin() depends on ttyslot() to find out which tty to look for in /etc/utmp. ttyslot() looks for the first file descriptor of (0,1,2) that is a tty, then looks that up in /etc/utmp. To fool it, redirect standard input from /dev/null, standard output to some other user's terminal which must be writeable, and print out the return from getlogin() on standard error. As it stands, getlogin() is not a safe way to identify the caller of a program, unless you cross check with the (real) userid too. Can anyone see anything wrong with adding something like this to getlogin(), to avoid confusion? stat( ttyslot_result, statbuf); if (statbuf.st_uid != getuid()) return(0); -- Chris Ritson JANET: C.R.Ritson@uk.ac.newcastle PHONE: +44 91 222 8175 UUCP : ...!ukc!newcastle.ac.uk!C.R.Ritson ARPA : C.R.Ritson@newcastle.ac.uk SNAIL: Computing Laboratory, University of Newcastle upon Tyne, UK, NE1 7RU JANET: C.R.Ritson@uk.ac.newcastle PHONE: +44 91 222 8175 UUCP : ...!ukc!newcastle.ac.uk!C.R.Ritson ARPA : C.R.Ritson@newcastle.ac.uk SNAIL: Computing Laboratory, University of Newcastle upon Tyne, UK, NE1 7RU
maujf@warwick.ac.uk (Mike Taylor) (06/08/89)
[Someone (original reference lost) says:] > If this [cuserid()'s behaviour]is indeed a bug on other versions of > Unix ... The fact that it doesn't do what you want it to do doesn't make it a bug -- it's only a bug if it doesn't do what it *says* it does. If you want the login name of the user running the process, then you should use getpwuid(getuid())->pw_name. Cuserid() is specifically designed to do this only if its attempt to look up the name in /etc/utmp fails. ______________________________________________________________________________ Mike Taylor - {Christ,M{athemat,us}ic}ian ... Email to: mirk@uk.ac.warwick.cs