Re: Unexecutable Stack / Buffer Overflow Exploits...

Theodore Y. Ts'o (tytso@MIT.EDU)
Mon, 3 Jan 2000 13:51:30 -0500


Date: Mon, 3 Jan 2000 11:42:34 -0500 (EST)
From: Gregory Maxwell <greg@linuxpower.cx>

I have a statement which I like you to affirm or deny. It will clear up a
lot of things I think.

"If there is a remotely exploitable stack-smash attack for *ANY*
userspace application or daemon (i.e. Netscape or Sendmail) running
on ia32 Linux without the Solar Designer No-exec-patch, then there
*must* exists an exploit for that application on ia32 Linux *WITH*
that patch applied."

Let me modify that statement a little bit, just to make things more
concrete. IF the following conditions applies:

* There is an application which has has an exploitable
stack-smash attack on an IA32 Linux system, AND
* The attacker has access (or can recreate) to the binary
(otherwise you're depending on security through
obscurity), AND
* The the program is using any one of a number of simple, basic
libc functions (this rules out trivial, non-real-world
applications):
open, unlink, exec, rename, chmod, chown
(and in most cases(!): memcpy and strcpy)

THEN a knowledgeable attacker will be able to construct an attack which
will cause harm to that system even with the Solar Designer
no-exec-patch enabled.

Why do I say that? Because what you can do is overwrite the stack in a
carefully designed way to transfer control to that function, which can
then do damage. For example supose your real-life application has a
single call to strcpy() anywhere in the text segement. Then all you
have to do is to overrun the stack in the following way:

B---> ptr to static buffer in data segment
padding (to cover local variables)
ptr to static buffer in data segment
ptr to attack code (see below)
A---> ptr to "call strcpy" instruction in text segment
padding (to cover local variables)
copy of attack code

After the stack is overrun, the last thing the function does is adjust
the stack pointer to the end of its stack frame "A" and then it
returns. However, the stack at "A" contains not a pointer into
executable code on the stack (since we're assuming the stack might be
non-executable) but rather, to a "call strcpy" instruction in the text
segment. This causing a call to the libc function, which will then copy
the attack code into the data buffer, and then return to the middle of
whatever function the strcpy() call was contained in. When that
function returns (you ideally pick a function where the call to strcpy
is one of the last things that function does), that stack frame gets
destroyed, and now the return address at statck stack location "B"
transfers control to the data segment where the attack code has been
copied, and viola! It's off to the races.

(I just recently came up with the generalized memcpy/strcpy exploit, and
I'm pretty proud of it. It should work on most real-world binaries with
a stack-smashing vulnerability, even on a machine with the non-exec
stack hack patch installed.)

If you disagree, then what is your argument against this patch?
What if the patch was described as a tool to:

"To stop attacks made impossible by the patch and to make creating a
working attack a bit more difficult in cases where there is still possible
exploit"

Will there be some attacks which the Solar Designer patch will stop
outright, 100%? I'm pretty sure you could artificially construct a
daemon with a stack exploit which didn't use any interesting libc
functions. In fact, here's one:

/*
* To be run out of inetd
*/
main()
{
char foo[2];

read(0, &foo, 4096);
}

An exploit against this program, yes, would probably be stopped by the
Solar Designer patch (assuming there isn't anything interesting in
crt0.o). However, would the Solar Designer patch stop an attack against
a real world (useful) program that actually makes calls to silly libc
functions like strcpy, memcpy, open, chmod, etc.? That's a different
question, and I think that answer is no. So, the benefits of the patch
are seriously called into question.

Then you have to ask about the costs, and different people will come to
different conclusions about that. The limitations for compiler writers,
for example, and complications in the kernel do have a non-zero cost.
The people who cry "security at any cost" are minimizing these costs in
their minds, but not everyone is necessarily going to assume that
security is worth *any* cost. For example, if the cost is to keep your
computer unplugged from the network and from AC power at all times, the
cost would probably be regarded as too high by most people. :-)

Throught this discussion, I've come to the realization that I now would
prefer this patch NOT go into the standard kernel. Right now it does
protect me against more then it would if it went in. It's a selfish
desire, I suppose. :)

Exactly. It's doing you a certain amount of good because it's not that
common. But if everyone adopted the patch, its usefulness would go down
significantly. This is basically an example of the old "tradgedy of the
commons" paradox.

On the other hand, if the non-exec stack hack is rarely used, then
hopefully attackers won't adapt themselves to use evade non-exec patch,
and when they attack a machine that *does* have it enabled, hopefully
the sysadmin will notice something went awry, analyze it, and then fix
the real problem in the daemon, which will then get distributed to
everybody. Of course, it's wise not to rely on this, since some
attackers might just decide (based on this long discussion on the
linux-kernel list) to develop some of these exploits just out of the
technical challenge, and thus render the non-exec stack hack mostly
useless, and the attackers, mostly invisible. (Remember, an attack
which works against a non-exec stack hack machine will also work on a
machine with a stock krenel. So once the generalized attack mechanism
is devised and automated, the attackers might as well use it in all
cases, to minimize their chances of getting detected.)

- 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/