Path: utzoo!utgpu!water!watmath!clyde!att!rutgers!mailrus!cornell!uw-beaver!uw-june!ka From: ka@june.cs.washington.edu (Kenneth Almquist) Newsgroups: comp.unix.wizards Subject: Re: Setuid shell scripts (was System V Release 4 ...) Message-ID: <6133@june.cs.washington.edu> Date: 19 Oct 88 18:07:52 GMT References: <467@gould.doc.ic.ac.uk> <13958@mimsy.UUCP> <109@minya.UUCP> Organization: U of Washington, Computer Science, Seattle Lines: 61 John Chambers asks: > To be more specific, I'd sure like to know what it is about the > shell programming languages (Bourne, C, K, T, etc...) that make > them more risky than a C program. Here is a possibly incomplete list of problems: 1. The behavior of shell scripts can depend upon the environment variables passed in to them. The fix to explicitly set every shell variable that your shell procedure uses. Explicitly set shell variables to the empty string rather than assuming they will be initialized to the empty string by default. More important, explicitly set all shell variables that the shell refers to implicitly. This includes things like PATH and IFS. 2. The #! passes the name of the shell script as argv[1], but the shell does not understand about this convention and will interpret argv[1] as an option rather than as a file name if the first character of argv[1] is a minus sign. The fix is to write a little stub program in C for each setuid shell procedure. The stub program is setuid, and simply does an exec of the shell with argv[1] set to the full path name of the actual shell procedure. Since the path name of the shell procedure is hard coded into the stub, it is guaranteed not to start with a minus sign. The file containing the shell procedure should not be either setuid or executable, to ensure that all user invoke the stub rather than running the shell procedure directly. Aside from problems 1 and 2, there are also some more general issues: 3. People tend to use the shell for quick hacks which work right in most cases. But being a little bit insecure is like being a little bit pregnant. The fix is to put as much thought into writing a setuid shell procedure as you would into writing a setuid C program. In fact, writing a setuid shell procedure is *more* difficult that writing a setuid C program because the semantics of C are simpler. 4. When you write a shell procedure your code depends upon a large body of software: the shell and also all the programs that your shell procedure invokes. These programs change. Usually the changes are backward compatible enough for most purposes, but they may not achieve the level of backward compatibility required to preserve the security of a setuid shell script. For example, csh doesn't have IFS. If IFS were added to csh, most csh shell scripts would continue to work, but setuid csh scripts would have to be modified to set IFS to a standard value. The fix is to write setuid programs in C. OK, that last sentence deserves half a ":-)", but most of the time it's not worth the trouble to write a setuid program as a shell procedure when you have C available. An exception is when you need to invoke an operation (such as ps(1)) which requires you to run a separate program. This is enough of a pain to do without the shell (note that popen invokes the shell) that I might use a setuid shell procedure. In any case, this discussion started with the claim that System V Release 4 would ignore the setuid bits when interpreting "#!". This affects various interpreted languages like ICON, but as I explained in point 2 above, setuid shell procedures implemented using a C language stub (which is the only way I know of to implement setuid shell procedures if you want securely) don't use the #! facility at all. Kenneth Almquist