Re: Unexecutable Stack / Buffer Overflow Exploits...

Theodore Y. Ts'o (tytso@mit.edu)
Fri, 31 Dec 1999 18:46:47 -0500


Date: Fri, 31 Dec 1999 19:46:55 +0100
From: Magnus Danielson <cfmd@swipnet.se>

Right, and for a big endian system it may still be usefull for some
architectures since you need to load the address into a register
before the instruction actually doing a jump/call is seen, so that
would be stripped of by strcpy. However, now that you have the jump
address in the register you migth as well do some operations on it,

Yes, '00' in the pointer will raise the bar, but it is kludgy (not to say it
is not usefull) and will be worked around pretty quickly (given some
intelligence on the attacker) and I am not sure I want to see that solution
around for very long, it gives me the chill when considering the long term
effects.

Umm, no. Before you can play games like masking to produce the desired
address in a register, you have to gain control first, which means you
need to overwrite the return address on the stack. If the attack code
is on the stack, and then the return address which you need to write
contains a null, and as long as some routine which is expecting a null
terminated string (i.e., strcpy) is used to overrun the on-stack buffer,
it will stop before it has a chance to write the entire return address.

This won't save you if the program is using memcpy, but with memcpy
there is an explicitly length passed in, and *hopefully* the programmer
has been bright enough to sanity-check the length before passing it into
memcpy.... but stupider things have happened in the past.

This also won't save you if the attacker knews the address of a static
buffer (which is in the data segment), and can store arbitrary data of
his/her choosing in that static buffer, and then overwrites the return
address on the stack to point to the static buffer. But then again, the
non-executable stack hack won't save you in this case either.

This is not as effective as having strcpy to actually _know_ the
end of the target, that would stopp the overrun attacks trough strcpy.
The methods for conveying that knowledge would either to fix the code to use
the safer cousins of the strcpy or by doing some knowledge transfer from the
compiler to the binary so that the libc routines can know it at runtime.

Actually, as long as frame pointers are used, it's possible on most
architectures for strcpy to crawl back on the stack looking for stack
frames, and then refuse to copy something that exceeds the bounds of a
stack frame. It's gross, and it's kludgy, and it would have to take
into account that some intervening subroutines (say, in an shared
library) may have been compiled with -fomit-frame-pointer, but it's not
that different to code; that's what gdb's "backtrace" command does,
after all.

Of course, all of these solutions are kludges. No question! The real
right answer is to get application programmers to use appropriate
defensive coding techniques, or if you're really desparate, compile
programs using something like Stackguard.

- Ted

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/