Re: Xserver stack smashed -- wrapper

From: Cotfas Vladimir-Marian (ulianovat_private)
Date: Wed Jan 14 1998 - 07:32:02 PST

  • Next message: Aleph One: "Linux inode.i_count overflow"

    >
    > Summary:
    >
    > On a system where X11R6-based Xserver (R5 is probably affected too) is
    > installed setuid or setgid (e.g. typical XFree86 installation has XF86_*
    > setuid root), local users can exploit a buffer overrun in its code and
    > gain extra privileges (e.g. root privileges when Xserver is setuid root).
    >
    >
    > Quick vulnerability check:
    >
    > X :00000000000000000000000000000000000000000000000000000000000000000\
    > 00000000000000000000000000000000000000000000000000000000000000000000\
    > 00000000000000000000000000000000000000000000000000000000000000000000\
    > 00000000000000000000000000000000000000000000000000000000000000000000\
    > 00000000000000000000000000000000000000000000000000000000000000000000\
    > 00000000000000000000000000000000000000000000000000000000000000000000\
    > 00000000000000000000000000000000000000000000000000000000000000000009
    >
    > (add -nolock for XFree86, change X to whatever name your Xserver has)
    >
    > Vulnerable Xserver will crash (Segmentation fault).
    >
    > (Note: machines immunized against stack smashing--e.g. Linux boxes with
    > Solar Designer's kernel patch--are probably not vulnerable.)
    >
    >
    > Quick fix:
    >
    > * remove setuid/setgid bit from all installed Xservers
    > * use xdm or a safe setuid wrapper to start Xserver
    >
    >
    > Details:
    >
    > X11R6.x Xserver recognizes a runtime argument specifying the desired
    > display (e.g. X :1). It accepts ANY value regardless of its length
    > and contents (save from the initial colon).
    >
    > Excerpt from xc/programs/Xserver/os/access.c (X11R6.3)
    >
    > /* Reset access control list to initial hosts */
    > void
    > ResetHosts (display)
    >     char *display;
    > {
    >     register HOST       *host;
    >     char                lhostname[120], ohostname[120];
    >     char                *hostname = ohostname;
    >     char                fname[100];
    >
    > [snip]
    >
    >     strcpy (fname, "/etc/X");
    >     strcat (fname, display);
    >     strcat (fname, ".hosts");
    >     if (fd = fopen (fname, "r"))
    > [snip]
    >
    > }
    >
    > Xserver calls ResetHosts() during its startup. A very long value of
    > "display" (100 + 2*120 + delta bytes) overflows "fname" and corrupts
    > the stack.
    >
    > An actual exploit is left as an exercise for the reader. :)
    >
    > There are probably other vulnerable places in Xserver code. (I have
    > spotted another buffer overrun in LockServer() (os/utils.c, XFree86
    > specific) but this one seems to be benign.) Anyone willing to pay me
    > big bucks for an exhaustive audit is welcome. :)
    >
    >
    > --Pavel Kankovsky aka Peak (troja.mff.cuni.cz network administration)
    >           [ Boycott Microsoft -- http://www.vcnet.com/bms ]
    >
    
    Here's a wrapper for this bug and for the older XF86 security vulnerability
    (i.e. XF86_XX -config /etc/shadow)
    
    Vladimir
    
    ----------------------------cut from here-------------------------------
    /*
      Description: X server wrapper
    
      Goals:
       1. wrap the "-config" security vulnerabillity
       2. wrap the :000000000000...00000000000000009 potential buffer overflow
    
      Instalation steps:
       0. Become root (su -)
       1. Modify the X_Server program variable according to your taste
          (i.e. the X server true path, not the link to it!)
       2. Compile this program as
            cc Xserver.c -O4 -o Xserver
       3. Copy the resulting binary to /usr/X11/bin, or whatever path you may have
       4. chmod 04711 Xserver
       5. Suppose your X server is called "XF86_S3"; issue a command
            chmod 0711 XF86_S3
       6. Remove the old link for X (e.g X -> /usr/X11/bin/XF86_S3)
       7. Make a new link
            ln -s /usr/X11/bin/Xserver /usr/X11/bin/X
    
       Copyright policy: the GNU Public License.
    
       This program is intended as a temporary patch for an existing X server;
       it is provided "as is", the author is not responsible for any
       direct/indirect damage(s) caused by its use.
    */
    
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <syslog.h>
    #include <pwd.h>
    #include <sys/types.h>
    
    /*
       This is intended for debugging porposes only.
       Do NOT define this for a normal usage!!
    */
    #define _DEBUG
    #define SIZE 1024
    
    /* guaranteed filled with NULLs by UNIX */
    char* args[SIZE];
    int argsCount = 0;
    
    char* sccsID =
      "@(#) X wrapper 1.0 Copyright (C) 1998 by Vadimir COTFAS (ulianovat_private), Jan 14th 1998";
    char *X_Server = "/usr/X11/bin/XF86_S3";
    
    int main(int argc, char* argv[])
    {
       int i;
       uid_t uid, euid;
       struct passwd* pass;
    
       openlog("Xserver", LOG_CONS|LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_AUTHPRIV);
       uid = getuid(); euid = geteuid();
    
       if(!((uid==0) || (euid==0))){
          fprintf(stderr,"Xserver: this program must be run as (setuid) root\n");
          exit(1);
       }
    
       pass = getpwuid(uid);
    
       for(i=0; i<argc; i++){
          char* p;
          if((index(argv[i],':') != NULL) && (strlen(argv[i]) > 2)){
             syslog(LOG_NOTICE, "potential buff ovrflw at arg #%d user %s",
                     i, pass->pw_name);
             continue;
          }
          if(strstr(argv[i], "-config")){
             syslog(LOG_NOTICE, "security vulnerability at arg #%d user %s \n",
                     i, pass->pw_name);
             i++;
             continue;
          }
          if(argsCount >= SIZE){
             syslog(LOG_NOTICE, "too many args (>1024) user %s \n", pass->pw_name);
             exit(1);
          }
          args[argsCount++] = argv[i];
       }
       args[argsCount] = NULL; /* just to be sure */
    
    #ifdef DEBUG
       for(i=0; i<argsCount; i++) printf("%s ", args[i]);
       printf("\n");
    #endif
    
       if(execv(X_Server, args) < 0){
         fprintf(stderr,"Xserver: could not execute the X server ``%s''\n", X_Server);
         exit(1);
       }
    
       /*NOTREACHED*/
       return 0;
    }
    /* EOF */----
    Network Guru Administrator
    http://www.mecanica.math.unibuc.ro/~ulianov
    Alternate e-mail ulianovat_private
    Home Phone: 40-01-7776598, 40-068-181613
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:38:54 PDT