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