Bugtraq mailing list archives
Interim solution for ps
From: jzbiciak () DALDD SC TI COM (Joe Zbiciak)
Date: Mon, 19 May 1997 18:26:58 -0500
All, Here's a generic wrapper I've written that you can use as an interim solution for wrapping /usr/bin/ps and /usr/ucb/ps. (/usr/ucb/ps looks to be similarly vulnerable.) The code is fairly well documented IMHO, and should be adaptable enough to wrap just about any program. This wrapper also filters environment variables, so if you have binaries which blindly trust certain variables (NLSPATH is a common one in Solaris), you can filter out those variables. (You could also fairly trivially add in default values for some variables if you needed to, such as for NLSPATH.) Finally, this wrapper will log exploit attempts to syslog if you configure that option. The log facility, log priority, and log ident are all configurable with #defines. I've currently set the code to LOG_ALERT on LOG_LOCAL0, with ident "wrapper". To prevent problems with syslog, the wrapper even limits the number of characters it writes per log message. (Note: This limit is on the number of characters per message, not including the identifier, PID, etc.) I make no guarantee or warranty about this code; it looks good/works fine for me. :-) If you have problems configuring this wrapper for a particular program, first read all the comments in the source, and then email me if you still can't figure it out. :-) Incidentally, it's safe to leave ps lying around without the suid-bit; it'll happily list the calling user's own processes, and those processes alone. That's one of the wonderful advantages of a /proc based ps. :-) Enjoy! --Joe --- wrapper.c /*****************************************************************/ /* Generic wrapper to prevent exploitation of suid/sgid programs */ /* J. Zbiciak, 5/19/97 */ /*****************************************************************/ #include <stdio.h> #include <syslog.h> #include <strings.h> #include <unistd.h> #include <errno.h> static char rcsid[]="$Id: wrapper.c,v 1.1 1997/05/19 22:48:03 jzbiciak Exp $"; /**************************************************************************/ /* To install, move wrapped executable to a different file name. (I like */ /* just appending an underscore '_' to the filename.) Then, remove the */ /* offending permission bit. Finally, place this program in the wrapped */ /* program's place with the appropriate permissions. Enjoy! */ /**************************************************************************/ /* Tunable values per program being wrapped */ #define WRAPPED "/usr/bin/ps" /* Set to full path of wrapped executable */ #define REALBIN WRAPPED"_" /* Usually can be left untouched. */ #define MAX_ARG (32) /* Maximum argv parameter length. */ #define SYSLOG 1 /* Enable/disable SYSLOGging */ #define FACILITY LOG_LOCAL0 /* Facility to syslog() to */ #define PRIORITY LOG_ALERT /* Priority level for syslog() */ #define LOGIDENT "wrapper" /* How to identify myself to syslog() */ typedef struct tEnvInfo { char * env; /* Environment var name with trailing '=' */ int name_len; /* Length of name (including '=') */ int max_len; /* Max length of value assignable to var */ } TEnvInfo; /* aside: trailing '=' is necessary to prevent problems with variables */ /* whose names prefix each other. */ TEnvInfo allowed_env [] = /* Environ. vars we allow program to see */ { { "COLUMNS=", 8, 4 }, { "LC_CTYPE=", 9, 64 }, { "LC_MESSAGES=", 11, 64 }, { "LC_TIME=", 8, 64 }, { "LOGNAME=", 8, 16 }, { "TERM=", 5, 16 }, { "USER=", 5, 16 }, }; #define NUM_ALLOWED_ENV (sizeof(allowed_env)/sizeof(TEnvInfo)) /* Internal use only -- shouldn't need to adjust, usually */ #define MSG_LEN (192) /* Maximum output message length. */ #define MAX_LOG (64) /* Maximum length per call to syslog() */ #ifndef SYSLOG #error Define "SYSLOG" to be either 1 or 0 explicitly #endif /* No user serviceable parts inside (End of configurable options) */ /* Log a message to syslog, and abort */ void log(char * s) { #if SYSLOG char buf[MAX_LOG]; int l; l=strlen(s); /* Open up syslog; use "Local0" facility */ openlog(LOGIDENT "[" WRAPPED "]",LOG_PID,FACILITY); do { strncpy(buf,s,MAX_LOG-1); buf[MAX_LOG-1]=0; syslog (PRIORITY,buf); l-=64; if (l>0) s+=MAX_LOG-1; } while (l>0); closelog(); #endif exit(1); } /* The main event */ int main(int argc, char * argv[], char *envp[]) { int i,j,k; char buf[MSG_LEN]; /* Check all of argv. Log and exit if any args have length > MAX_ARG */ for (i=0;i<argc && argv[i]!=0;i++) { if (strlen(argv[i])>MAX_ARG) { printf("Error: Aborting!\n" " Excessive commandline argument length: '%s'\n", argv[i]); /* Safe since uid/gid etc. are max 5 chars apiece */ sprintf(buf, "Attempted overrun (argv): " "uid=%.5d gid=%.5d euid=%.5d egid=%.5d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()); log(buf); exit(1); /* safety net */ } } /* Check all of envp. Throw out any environment variables which aren't in "allowed_env[]". If any variables permitted by "allowed_env[]" are too long, log and exit. */ for (i=j=0; envp[i]!=0; i++) { for (k=0;k<NUM_ALLOWED_ENV;k++) { if (strncmp(envp[i], allowed_env[k].env, allowed_env[k].name_len)==0) break; } if (k!=NUM_ALLOWED_ENV) { if (strlen(envp[i]) > allowed_env[k].max_len+allowed_env[k].name_len) { printf("Error: Aborting!\n" " Excessive environment variable length: '%s'\n", envp[i]); /* Safe because we have control over allowed_env[] */ sprintf(buf, "Attempted overrun (env var '%s'): " "uid=%.5d gid=%.5d euid=%.5d egid=%.5d\n", allowed_env[k].env, (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()); log(buf); exit(1); /* safety net */ } envp[j++]=envp[i]; } if (j>NUM_ALLOWED_ENV) { log("Internal error to wrapper -- too many allowed env vars"); exit(1); /* safety net */ } } envp[j]=0; /* If we make it this far, we're good to go. */ argv[0]=WRAPPED; execve(REALBIN, argv, envp); /* Safe, because errno number is very few chars */ sprintf(buf, "execve failed! errno=%.5d\n",errno); perror("execve() failed"); log(buf); exit(1); /* safety net */ } --- EOF -- +--------------Joseph Zbiciak--------------+ |- - - - jzbiciak () daldd sc ti com - - - - -| | - - http://ee1.bradley.edu/~im14u2c/ - - | Not your average "Joe." |- - - - Texas Instruments, Dallas - - - -| +-------#include <std_disclaimer.h>--------+
Current thread:
- Reminder for irix ppl Nafees Bin Zafar (May 14)
- Re: Reminder for irix ppl Mike Neuman (May 15)
- Vulnerability in Elm-ME+ John Goerzen (May 15)
- Re: Vulnerability in Elm-ME+ Kari E. Hurtta (May 17)
- Finally, most of an exploit for Solaris 2.5.1's ps. Joe Zbiciak (May 17)
- Re: Finally, most of an exploit for Solaris 2.5.1's ps. Adam Morrison (May 19)
- Re: Finally, most of an exploit for Solaris 2.5.1's ps. Joe Zbiciak (May 19)
- Interim solution for ps Joe Zbiciak (May 19)
- Re: Interim solution for ps Steven Kirby (May 19)
- The rest of the exploit is here! Solaris 2.5.1 ps! Joe Zbiciak (May 18)