Bugtraq mailing list archives
PAX & the Future of buffer overflows ?
From: Crispin Cowan <crispin () WIREX COM>
Date: Tue, 31 Oct 2000 00:58:06 -0800
Thomas Dullien wrote:
Well, I assume you all have read the PaX paper at pageexec.virtualave.net.
Yep :-)
So it is possible to have readable, non-executable memory pages, at a not too bad performance hit of up to 10%. This is very cool. The traditional way of exploiting buffer overruns and format string vulnerabilities are pretty much non-functional if the OS kernel can ensure no writable page can be executed.
This part confuses me :-) Thomas' analysis below reminds us that making data pages non-executable leaves open the return-into-libc style of attacks. We predicted this kind of work-around for segment access controls in our paper early this year dissecting the buffer overflow problem space http://immunix.org/StackGuard/discex00.pdf The paper classifies buffer overflow attacks in two dimensions: * How the attack code is placed in the victim program's address space. There are two options: o Inject it: i.e. the attack code is written into data space. PAXstops this o It is already there: i.e. use a variation on return-into-libc. * Making the program jump to the attack code: This is generally done by changing a "code pointer" to point to the attack code, and waiting for the program to dereference the code pointer. The choice is which code pointer to change, which in turn depends on what the buffer is adjacent to: o Activation Records: i.e. function call return addresses, the classic "stack smash" from Aleph's cookbook. o Function Pointers: i.e. "void (* foo)()" declares the variable foo to be a pointer to a function returning void. The SuperProbe exploit of long ago, and many since, have used buffer overflows to change function pointers that happened to be adjacent to overflowable buffers. o Longjmp Buffers: When you do a setjmp(buffer), it stores your state in the buffer structure, including your program counter (PC). Subsequent longjmp(buffer) calls will jump you to that PC value. If buffer is adjacent to an overflowable buffer, then the attacker can change the PC value to point to the attack code. Memory segment access controls are fundamentally a script kiddie defense. Any attack that can be defeated by PAX, can also be re-worked to not depend on injecting the shell code. Therefore, by any classical definition of "security", it fails to actually provide defense, making it an obscurity defense that merely makes it more difficult to write exploits. Openwall http://www.openwall.com/linux/ provides a similar benefit, but without the 10% performance overhead. It is a really cool hack that you can implement non-executable data pages on the x86 ISA that does not support read/no-exec pages by messing with the TLB caches. But I don't really see the security value. I am *not* saying that PAX has no value. However, that value is restricted to debugging. Clearly executing data pages in the common case is an error, and when testing a program, you want to know about it. However, as Saltzer & Schroeder tell us in their seminal paper http://web.mit.edu/Saltzer/www/publications/protection/index.html obscurity does not equal access control, because the intelligent attacker will simply adapt to the obscure requirements.
Does this mean buffer overflows and format string vulnerabilities are dead? On systems that actually implement this kind of protection, they are going to have a lot less importance than before. Cutting & pasting shellcode just won't do it any more. So what can you still do with a buffer overrun ? This depends largely on the particular situation and has to be decided on a case-by-case basis, but generally a stack overflow can still be used to issue one libc/msvcrt call with arbitrary arguments as long as they do not include a NULL byte as args. Now with a single system() or exec() you can do a few funky things, and even memcpy() is a very cool thing to execute. If you manage to keep the stack in a consistent state and you don't crash the application, you might even be able to do this several times in a row. Format string vulnerabilities still allow you to write to any location in memory. Patching internal variables and overwriting vtable pointers is a funny thing to do. So to wrap it up: The PaX project is IMO awesome. But even if buffer over- runs and format string vulnerabilities loose the instant remote root shell danger, they can still allow a skilled attacker to do things he's not supposed to. And its only up to the creativity of the attacker what he does. So it raises the bar for us all :) but just might make writing exploits an interesting business again.
Now that's the part of the analysis I can agree with. :-) Crispin -- Crispin Cowan, Ph.D. Chief Research Scientist, WireX Communications, Inc. http://wirex.com Free Hardened Linux Distribution: http://immunix.org
Current thread:
- PAX & the Future of buffer overflows ? Crispin Cowan (Nov 03)
- <Possible follow-ups>
- Re: PAX & the Future of buffer overflows ? Crispin Cowan (Nov 04)