sacrificing performance for confusion
Chuck Swiger
cswiger at mac.com
Thu Jun 26 18:23:35 PDT 2003
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
More information about the freebsd-performance
mailing list