Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
Subject: Vulnerability in Solaris ufsrestore
From: Job de Haas (jobITSX.COM)
Date: Wed Jun 14 2000 - 06:59:05 CDT


Reading RFP's great initiative on the disclosure policy
( http://www.wiretrip.net/rfp/policy.html ), here is the scoop
on a local root exploit I reported to Sun on May 18th. I received
confirmation on the reception, stated I would disclose in three weeks and
heard nothing since. I've had better experiences with CERT ...

The bug is for Solaris 2.x up to the latest (8). The most disturbing part
about the whole thing is that it remains after someone actually tried to fix
it. I could write a whole blurb about it but a recent thread on AntiSniff
showed all the issues.


The ufsrestore has an overflow in a buffer holding the pathname/command for
an interactive session.

The buffer overflow can lead to local root compromise.

The removal of an executable stack will make exploitation of this
vulnerability very difficult and likely impossible because
/usr/lib/fs/ufs/ufsrestore is a statically linked executable. However,
removal of the setuid bit will in almost every case be acceptable and will
be a guaranteed workaround.

Affected systems
The exploit has only been tested on Solaris 8 sun4u. However it seems
likely that every previous version is vulnerable including any security
patches previously created.

The programs for performing backups have a history of security problems.
Different Unix distributions have chosen different ways to go about fixing
these. Reducing the permissions has been one of the steps the free Unix
distributions have chosen. Further, most buffer overflow conditions have
been fixed over time. From an older public version of the source a specific
condition can be seen in interactive.c:


getcmd(curdir, cmd, name, size, ap)

        char output[BUFSIZ];
                (void) strcpy(output, curdir);
                (void) strcat(output, "/");
                (void) strcat(output, rawname);
                canon(output, name, size);

A fix for FreeBSD with the comment "Prevent buffer overflow with extra
long arguments." shows at (URL broken off):


- (void) strcpy(output, curdir);
- (void) strcat(output, "/");
- (void) strcat(output, rawname);
+ snprintf(output, sizeof(output), "%s/%s", curdir, rawname);

However, when disassembling /usr/lib/fs/ufs/ufsrestore, we find:

0x00012538: add %fp, -0x404, %o0
0x0001253c: mov %l3, %o1
0x00012540: call 0x000c058c
0x00012544: mov 0x401, %o2
0x00012548: sethi %hi(0xd9c00), %g2
0x0001254c: add %fp, -0x404, %o0
0x00012550: stb %g0, [%fp - 0x4]
0x00012554: add %g2, 0x64, %o1
0x00012558: call 0x00099f34
0x0001255c: mov 0x401, %o2
0x00012560: add %fp, -0x404, %o0
0x00012564: mov %i3, %o1
0x00012568: stb %g0, [%fp - 0x4]
0x0001256c: call 0x00099f34
0x00012570: mov 0x401, %o2

A reconstruction of what the C-code for this segment would look like, gives
something like:

                (void) strncpy(output, curdir, BUFSIZ);
                output[BUFSIZ-1] = '\0';
                (void) strncat(output, "/", BUFSIZ);
                output[BUFSIZ-1] = '\0';
                (void) strncat(output, rawname, BUFSIZ);
                output[BUFSIZ-1] = '\0';

It needs no further explanation that this is not the way to fix a buffer

The attached demonstration is in two parts. A script that needs to be run as
root to create a proper dump file and C code for a program to exploit the
problem with this dump file. The C program is a little big due to some
toying with fixed shell code positioning that I didnt quite finish.



Job de Haas         jobitsx.com
ITSX bv      http://www.itsx.com