Path: utzoo!utgpu!watmath!clyde!att!rutgers!mailrus!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery From: dg@lakart.UUCP (David Goodenough) Newsgroups: comp.sources.misc Subject: v05i063: Solving the setuid script problem Message-ID: <8811231522.AA14884@lakart.UUCP> Date: 3 Dec 88 00:27:57 GMT Sender: allbery@ncoast.UUCP Reply-To: dg@lakart.UUCP (David Goodenough) Lines: 139 Approved: allbery@ncoast.UUCP Posting-number: Volume 5, Issue 63 Submitted-by: "David Goodenough"Archive-name: secure [Any setuid gurus want to say whether this is actually secure or not? ++bsa] After all the discussion about the lack of security of setuid shell scripts, I put the following together. It runs shell scripts, but is a little more careful as to what it will run. There's no makefile - just compile this, copy it to /bin/secure, chown it to root, and chmod it 4755. secure.8 describes the layout of /etc/secure - it's just a line for each safe shell script, containing the full pathname first, and the numeric uid the run the script. -- dg@lakart.UUCP - David Goodenough +---+ | +-+-+ ....... !harvard!xait!lakart!dg +-+-+ | AKA: dg%lakart.uucp@harvard.harvard.edu +---+ --- cut here --- cut here --- cut here --- cut here --- cut here --- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the '#! /bin/sh' line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (NOT csh) to create the files: # A: secure.c # B: secure.8 # # Unwrapping with no options prevents overwriting files that already exist; # giving a '-c' switch causes files to be overwritten regardless. # # wrapped by dg@lakart(David Goodenough) on Wed Nov 23 10:13:18 EST 1988 # if test -f secure.c -a x$1 != x-c then echo shar: file secure.c already exists else echo shar: extracting secure.c sed "s/^X//" <<\##__EOF..secure.c__## >secure.c X#include X X#define SECURE "/etc/secure" X Xmain(n, a) Xchar **a; X { X int uid; X FILE *fp; X char program[100]; X X if (strcmp(a[0], "SEC-URE"))/* I'm damned if I know why this is */ X { /* necessary, but it is */ X (void) strcpy(program, a[0]); X a[0] = "SEC-URE"; X execv(program, a); /* re exec ourselves so setuid bits work */ X exit(1); /* this should never happen */ X } X if ((fp = fopen(a[1], "r")) == (FILE *) NULL) X exit(1); /* file not found */ X (void) fclose(fp); X if (a[1][0] != '/') X exit(1); /* only pass an absolute pathname to /bin/sh */ X if ((fp = fopen(SECURE, "r")) == (FILE *) NULL) X exit(1); /* can't find the file of secure programs */ X while (fscanf(fp, "%s %d", program, &uid) == 2) X { X if (strcmp(program, a[1]) == 0) X { /* aha ..... we found our program */ X (void) fclose(fp); X (void) unsetenv("IFS"); X /* tweak the environment for added safety */ X (void) setenv("PATH", "/bin:/usr/bin", 1); X (void) setuid(uid); /* set the uid */ X a[0] = "-sh"; X execv("/bin/sh", a); X exit(1); /* this should never happen */ X } X } X exit(1); /* come here if we didn't find the program */ X } ##__EOF..secure.c__## fi if test -f secure.8 -a x$1 != x-c then echo shar: file secure.8 already exists else echo shar: extracting secure.8 sed "s/^X//" <<\##__EOF..secure.8__## >secure.8 X.\" dg@lakart - David Goodenough Wed Nov 23 09:47:12 EST 1988 X.\" X.TH SECURE 8 "Nov 23, 1988" X.UC 4 X.SH NAME X.B secure X\- run setuid shell scripts safely X.SH SYNOPSIS X.B #! /bin/secure X.br X.SH DESCRIPTION X.B Secure Xis never normally executed from a shell. Instead it can be used Xas the interpreter for shell scripts that need to be run setuid someone Xelse: this is done by making the first line of the script X.PP X.ti+5n X#! /bin/secure X.PP Xrather than the usual X.PP X.ti+5n X#! /bin/sh X.PP X.B Secure Xdetermines if a script can be safely run by looking in X/etc/secure. This is a list of secure shell scripts, and the numeric Xuser id that the script is to be run with. A typical line from X/etc/secure might be X.PP X.ti+5n X/usr/script 0 X.PP Xwhich would mean that /usr/script should be run as root. X.PP XBecause X.B secure Xwill only Xexec a pathname beginning with '/', that comes from /etc/secure, it Xcannot be used to illegally gain root access. X.PP XIn addition, for the sake of security, X.B secure Xsets the PATH environment variable back to a simple default, and deletes Xthe IFS environment variable. X.SH "SEE ALSO" X.BR sh (1), ##__EOF..secure.8__## fi # end of shell archive exit 0