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.
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):
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 overflow.
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 email@example.com ITSX bv http://www.itsx.com