More buffer overrun crap -- Solaris 2.5.1 /usr/bin/ps

Joe Zbiciak (jzbiciak@MICRO.TI.COM)
Sat, 10 May 1997 08:15:43 -0500

Hi all,

While the last buffer overrun I found in /usr/bin/ps wasn't *obviously*
exploitable, I've done some more digging; it may indeed be exploitable.
Also, there's another buffer overrun in /usr/bin/ps, related to getopt()
This latter buffer overrun is more serious, IMHO, in that it could effect
multiple programs -- it's specific to getopt(), not ps.

I've not been able to successfully construct an exploit yet; this is
partially due to my relative infamiliarity with Sparc assembler and
Solaris function calling conventions. Hopefully, somebody can put
the pieces together for me from the information below.

The first tidbit is related to the original buffer overflow I found,
wrt. to all of the "option" receiving arguments. These options are
copied into a statically allocated buffer; at position 96 beyond the
start of this buffer is the static variable "environ". An additional
864 bytes beyond that is the static variable "optarg", which tells
getopt where to place the argument of a commandline switch. Overwriting
this to point into someplace interesting, such as the Procedure Linkage
Table at 0xef78267c might allow you to install an exploit on a second
commandline argument. ie.

"ps -u '.....smash optarg....' -g 'exploit code here'"

The hitch is that there's a couple other important variables between
optarg and environ which may make this non-trivial. Most notable is
optind, which is used to index into argv. Trashing that may break the
whole works.

The second tidbit is an apparent buffer overrun in getopt() itself; it
blindly trusts argv[0] and it appears to generate its error message into
a local buffer. :-) The basic form of the error message is

"%s: -- illegal option %c\n"

By passing a large argv[0] (using execl), it is possible to smash the
stack. *Note* It appears that a couple local variables to getopt need
to be preserved in order to allow getopt to actually return without a
segv. The easiest way I was able to determine what values to leave
where was using gdb on a non-suid copy of the executable being
examined. (This note looks like it's only true if the first "illegal
option" is not the last option in an argv[] slot.)

This doesn't appear directly exploitable from ps, since it is called from
the top-level function (_cg89_used() -- I assume that's main()), which
apparently exits using exit(). Other programs which call getopt from
a deeper level may be exploitable in this manner.

In any case, even if these potential vulnerability aren't as exploitable
as I might think, I would feel much safer if Sun were to patch these.

Regards,

--Joe

--
 +--------------Joseph Zbiciak--------------+
 |- - - - - jzbiciak@micro.ti.com  - - - - -|
 | - - http://ee1.bradley.edu/~im14u2c/ - - |      Not your average "Joe."
 |- - - - Texas Instruments,  Dallas - - - -|
 +-------#include <std_disclaimer.h>--------+