Great Circle Associates Firewalls
(November 1995)
 

Indexed By Date: [Previous] [Next] Indexed By Thread: [Previous] [Next]

Subject: Re: chroot/setuid vs type enforcement
From: Dermot Tynan <dtynan @ fws . ilo . dec . com>
Organization: Digital Firewall Engineering
Date: Wed, 29 Nov 1995 15:57:46 +0000 (GMT)
To: Alex . Pakter @ omnitel . it (Alex Pakter)
Cc: stockwel @ sctc . com, jeromie @ garrison . com, firewalls @ GreatCircle . COM
In-reply-to: <199511291005 . LAA21342 @ joanne . omnitel . it> from "Alex Pakter" at Nov 29, 95 11:05:31 am

Alex Pakter wrote:
> 
> QUESTION: How does it work?  OK, you feed the server too much input, it
> overwrites the (supposedly stack-allocated) buffer, and writes what you want
> onto the programs's stack.  And then?  How to you get from there to a 
> break-in?

I know of at least two methods for subverting a system using buffer
overruns.  Take the following (static) declarations...

char	buffer[512];
char	prog[64];

The program initializes prog[] to contain the name of some process
it wants to fire off, such as /sbin/sendmail.  It then uses a gets()
call to fill buffer[] with data that I provide.  There are no controls
on how much data gets() will accept.  The 513th byte will be deposited
into prog[0].  If I send a very long string, with some data at the
front, nulls up to 512, and then "/bin/sh\0" as the next 8 bytes, I've
subverted the program.  My "mail message" is then directed to /bin/sh
instead of sendmail.  The second example is more difficult and requires
a CPU architecture which *isn't* split I&D.  Essentially I hand-code
a little program which opens a file, and spits some data into it.
Perhaps I have a small program to read from a socket, put the data into
another executable, and then run it.  I assemble this program to run
in the stack area of the buffer (presuming of course that "buffer[]"
in this case is an automatic variable), and rewrite the return address
on the stack.  The average stack (not all, mind you) works downward.
If we look at high memory, where the stack is before the call, the
return program counter is pushed (down), the frame pointer is usually
pushed, and any register variables which need to be saved.  Then,
the size of the auto variables is subtracted from the stack pointer.
Thus, if we had a little 16-bit box, with a stack pointer of 0xf000,
we'd have a stack frame as follows;

	0xf000:	<return address>
	0xeffe:	<old frame pointer>
	0xeffc:	<register variable>
	0xeffa:	<register variable>
	.
	.
	.
	0xedfa: <start of 512 byte buffer>

I've given a simple response for the gets() call, followed by a few
nulls, and perhaps at 0xee00 I have my mini bootstrap program.  I
blow away the register variables and the frame pointer, and replace
the return address with 0xee00.  The routine returns, not to the
original caller but to my mini-stack-routine.

There are other methods, but you get the general idea.
					- Der
-- 
Dermot Tynan						+353 91 754608
dtynan @
 ilo .
 dec .
 com					 DTN: 822-4608

Digital Equipment International BV, Galway, Ireland


References:
Indexed By Date Previous: Re: chroot/setuid vs type enforcement
From: "william.wells" <william . wells @ damark . com>
Next: Re: SDI's Time-Synched SecurIDs (2 of 3)
From: woods @ ncar . ucar . edu (Greg Woods)
Indexed By Thread Previous: Re: chroot/setuid vs type enforcement
From: Alex Pakter <Alex . Pakter @ omnitel . it>
Next: Re: chroot/setuid vs type enforcement
From: "william.wells" <william . wells @ damark . com>

Google
 
Search Internet Search www.greatcircle.com