Path: utzoo!mnetor!uunet!husc6!sri-unix!quintus!ok From: ok@quintus.UUCP (Richard A. O'Keefe) Newsgroups: comp.lang.c Subject: Re: system Message-ID: <550@cresswell.quintus.UUCP> Date: 20 Jan 88 00:03:06 GMT References: <127@dcrbg1.UUCP> <7118@brl-smoke.ARPA> <4790@tut.cis.ohio-state.edu> Organization: Quintus Computer Systems, Mountain View, CA Lines: 78 Keywords: c program Summary: leashing system() In article <4790@tut.cis.ohio-state.edu>, lvc@tut.cis.ohio-state.edu (Lawrence V. Cipriani) writes: > In article <7118@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) ) writes: > > fflush( stdout ); > > if ( system( "date" ) != 0 ) /* print a time stamp on stdout */ > > error( "cannot execute \"date\" command" ); > > ... > > > System is probably one of the most abused functions in the C > library. This is an example of poor use, sorry Mr. Gwyn. There > are security problems with system() on UNIX. If the program user > sets their PATH so that it searches other than "non-standard" > directories before searching "standard" there is the potentional > for running the wrong program. This is deadly if the program using > system() is setuid/setgid. > > What to do about it? When the program starts up, reset the PATH > and IFS environment variables to something sensible, use full > path names (unfortunately you will lose portability here) to the > programs you are executing. Pathnames can be isolated in a > header file so this isn't a big issue. > There is a better way. Instead of calling system("date") you call system("PATH=/bin:/usr/bin date") in System V, or system("PATH=/usr/ucb:/bin:/usr/bin date") in 4.xBSD. To keep system-dependency to one place, do cat >safesys.c <<'EOF' #include #ifdef SUN #define CMDSIZ 10240 #define STDENV "IFS= PATH=/usr/ucb:/bin:/usr/bin:/usr/5bin " #else #ifdef BSD #define CMDSIZ 10240 #define STDENV "IFS= PATH=/usr/ucb:/bin:/usr/bin " #else /* assume USG */ #define CMDSIZ 10240 /* check your manual! */ #define STDENV "IFS= PATH=/bin:/usr/bin " #endif #endif int safe_system(command) char *command; { char buffer[CMDSIZ]; static char stdenv[] = STDENV; assert(sizeof stdenv + strlen(command) <= sizeof buffer); sprintf(buffer, "%s%.*s", stdenv, sizeof buffer - sizeof stdenv, command); return system(buffer); } EOF A still better approach is to have safe_system() do a fork(), and have the child process reset its environment, do seteuid(getuid()) setegid(getgid()) and finally call system(). That takes more code than I care to include here. There isn't any special security problem with system(). The security problem is with setuid/setgid programs. If your program offers the user the opportunity to enter a UNIX command, the user will be *extremely* unhappy to find that he can't run any of his programs because you have smashed the $PATH variable! If your program wants to run a utility for its OWN benefit, where it cares that a specific program documented in the UNIX commands manual should be run, use safe_system(). If your program wants to run another program on behalf of the user, it should use system() and should NOT alter the $PATH variable.