Date: Thu, 26 Jun 2003 21:23:30 -0400 From: Chuck Swiger <cswiger@mac.com> To: "D. J. Bernstein" <djb@cr.yp.to> Cc: freebsd-performance@freebsd.org Subject: Re: sacrificing performance for confusion Message-ID: <3EFB9C92.4010807@mac.com> In-Reply-To: <20030626220945.75399.qmail@cr.yp.to> References: <20030626220945.75399.qmail@cr.yp.to>
next in thread | previous in thread | raw e-mail | index | archive | help
D. J. Bernstein wrote: >>Using VMM protection to forbid code execution within the DATA, BSS, heap, >>and stack (if one can) mitigates against a common class of problems-- > > I don't believe you. Show me a real program that's (1) vulnerable if > data/bss/heap/stack are executable and (2) invulnerable otherwise. The easy case of buffer overflows involves someone putting a string on the stack which then gets passed to evec()/CreateProc/system()/popen()/etc: such cases fail criterion (2). The more difficult to exploit form of buffer overflow that depends on VMM execute permissions for the data/stack/etc tend to result from overwrites the return address or stored PC register with an address that points to memory controlled by the intruder. In particular, a buffer overflow in signal handling code or setjmp/longjmp, where the data being overwritten is the signal handler trampoline or the saved processor environment (env) can be very nasty. Anyway, the exploited buffer contains code which opens a socket ties it to a /bin/sh, cmd.exe, or whatever. If the VMM protection permits this code to run, that is. But you asked for code. I didn't write the following, but let it stand for the many examples of Unix or Windows shellcode: http://www.pkix.net/~chuck/win32_cmd.s ...I'm sure you could find or write the equivalent for Unix/C. -- Take a look at the following exception handler delegate (in Objective C): http://www.pkix.net/~chuck/CrashCatcher/Examples/Advanced/ControllerCC.m ...and note the following chunk of code: // The string returned by this method will be included in each crash report static char signature[40]; - (const char *)CC_applicationSignature { if (hasCrashed) exit(1); // quit if generating second report strcpy(signature, "Tailor "); strcat(signature, [self versionString]); #ifdef DEBUG strcat(signature, " (built for DEBUG)"); #endif return signature; } This code gets called after an exception has been handled, such as a Unix signal. If the buffer was on the stack (automatic variable, dynamicly allocated by alloca(), whatever), and versionString was too long, someone could overflow the stack and write over the signal handler trampoline. Or the stored return address of the caller's stack frame; the details don't matter: the point is having the PC switch to an address on the stack/heap/DATA and run the exploit code. [ See http://www.pkix.net/~chuck/CrashCatcher/libCrashCatcher/CCTypes.h and the CC_SignalTrigger.h and .m files for a type of exception applicable to plain C, namely a Unix signal, rather than the more esoteric flavors. ] -- Furthermore, at http://www.pkix.net/~chuck/CrashCatcher/Examples/CrashDummy there is a demo app containing a number of different exception types: TriggerMapVector triggers = { // non-fatal report triggers { "dump", "forceADumpBacktrace" }, { "usr1", "sigusr1" }, // fatal report triggers { "free", "triggerMessageToFreedObject" }, { "subclass", "triggerSubclassResponsibility" }, { "segfault", "triggerSegmentFault" }, { "buserr", "triggerBusError" }, { "usr2", "sigusr2" }, // type decoding demonstration [indirect] triggers { "object", "objectAndSelectorDemo" }, { "string", "stringDemo" }, { "basic", "assortedTypeDemo" }, { NULL, NULL } }; However, I will also acknowledge that it may be the case that it may be possible for code to work around a non-executable stack as per http://secinf.net/info/unix/stack.txt, which concludes as: ]Hopefully, these exploits demonstrate that it is important to make sure that ]programs that run at an elevated privilege are free of buffer overflow bugs. ]The stack protection will certainly help protect you from the majority of ]intruders, but moderately competent intruders will probably be able to bypass ]it. ] ]I believe that these techniques could be adopted for use in a remote exploit. ]Assuming we go with the strcpy technique, the attacker would need to do ]several things. First of all, the attacker would need to put the fake stack ]frame somewhere in the buffer that was overflowed. Then the attacker would ]have to make educated guesses at a few things. These would be: the location ]that strcpy() is mapped at, a safe location to store the shellcode, and the ]location of the fake stack frame. You could make pretty educated guesses at all ]of these, so it might only require a small number of tries. Of course, the ]added time and interaction that this would involve certainly makes the stack ]protection useful. -- This being said, I didn't claim that a non-executable stack rendered a system _invulnerable_, simply that it mitigated the difficulty of an exploit. Let me also acknowledge that there are other ways of protecting the stack besides VMM hardware, such as: http://www.trl.ibm.com/projects/security/ssp/main.html -- -Chuck
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3EFB9C92.4010807>