Patch to prevent setuid bash shells

From: aleph1at_private
Date: Sat May 30 1998 - 10:04:26 PDT

  • Next message: RBL: "Re: FileMaker Door"

    This patches bash 1.4.15 to prevent setuid root shells.  Of course, this
    does not totally secure a system.  A buffer overflow could run /bin/csh
    instead of /bin/sh, or any other command.
    
    Not only does this patch prevent setuid root shells from spawning, but it
    keeps a log file of all attempts, kills the user, and prevents them from
    logging in again.  The administrator can monitor the log file and decide if
    the person should be allowed back.
    
    This blocks logins using the ~/.nologin file, I'm not sure if this works on
    all systems, but it does work on mine.
    
    All instances of the user logged in while the buffer overflow happens are
    killed.  This keeps the intruder from attempting any other attacks.
    
    This is my first attempt at a patch, so if I did it wrong don't mock me too
    much =)
    
    My theory is, if you can catch an intruder attempting a known attack, they
    won't get a chance to exploit any unknown attacks.
    
    ------------------ CUT HERE --------------------
    --- shell.c     Thu Apr  6 16:45:00 1995
    +++ newshell.c  Sat May 30 12:31:44 1998
    @@ -29,6 +29,8 @@
       Birthdate:
       Sunday, January 10th, 1988.
       Initial author: Brian Fox
    +  Modified by: Ryan Veety [ryanat_private]
    +     - now doesn't allow setuid shells, kills anyone that attempts them.
     */
     #define INSTALL_DEBUG_MODE
    
    @@ -41,6 +43,7 @@
     #include <pwd.h>
     #include "posixstat.h"
     #include "bashansi.h"
    +#include <utmp.h>
    
     #if defined (HAVE_VARARGS_H)
     #include <varargs.h>
    @@ -247,6 +250,10 @@
       int arg_index, locally_skip_execution;
       int top_level_arg_index, read_from_stdin;
       FILE *default_input;
    +  FILE *rootshell;
    +  FILE *nologin_file;
    +  char* nologin;
    +  struct utmp* cutmp;
    
       /* There is a bug in the NeXT 2.1 rlogind that causes opens
          of /dev/tty to fail. */
    @@ -275,8 +282,47 @@
       current_user.egid = getegid ();
    
       /* See whether or not we are running setuid or setgid. */
    -  privileged_mode = (current_user.uid != current_user.euid) ||
    -                   (current_user.gid != current_user.egid);
    +  if(privileged_mode = (current_user.uid != current_user.euid) ||
    +                   (current_user.gid != current_user.egid) != 0)
    +  {
    +
    +    if(current_user.euid == 0)
    +    {
    +  /* Use the passwd file to get the users's login from the uid */
    +      struct passwd *entry = getpwuid (current_user.uid);
    +
    +  /* Give a nice warning to the user */
    +      printf("******************************************************\n");
    +      printf("*                Root Shell detected!                *\n");
    +      printf("*   This has been logged, and your account may be    *\n");
    +      printf("*               terminated as a result.              *\n");
    +      printf("******************************************************\n");
    +
    +  /* Well, we are running as root...so we can write to this file =) */
    +  /* You can change this to any kind of administrator warning       */
    +      rootshell=fopen("/usr/local/secure/rootshell", "a");
    +      if(rootshell != NULL)
    +      {
    +         fprintf(rootshell, "SUID ROOT DETECTED from UID %d [%s].\n", current_user.uid, entry->pw_name);
    +         fclose(rootshell);
    +      }
    +  /* Now its time to get rid of this guy!  */
    +      nologin = (char*)malloc(strlen(entry->pw_dir) + strlen("/.nologin") +1);
    +      sprintf(nologin, "%s/.nologin", entry->pw_dir);
    +      nologin_file = fopen(nologin, "w");
    +      if(nologin_file) fclose(nologin_file);
    +      while((cutmp=getutent()) != NULL)
    +         if(strncmp(cutmp->ut_user, entry->pw_name, 8) == 0)
    +            kill(cutmp->ut_pid, SIGKILL);
    +      return 1;
    +    }
    +    else
    +    {
    +  /* In case it is a setuid shell of bin, mail, ...   */
    +      printf("Sorry, I don't allow setuid shells.\n");
    +      return 1;
    +    }
    +  }
    
       posixly_correct = (getenv ("POSIXLY_CORRECT") != (char *)NULL) ||
                        (getenv ("POSIX_PEDANTIC") != (char *)NULL);
    
    -------------------- CUT HERE -----------------------
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:55:52 PDT