Friday, September 21, 2007

Still more separation of code and data

Separating code from data is a HUGE problem (possibly a root of all remote code execution evil). Here's more info, some of it new, some of it very old ...

There's a variety of vulnerabilities discovered recently that all involve document file types that either: A) allow executable code or script (which should be treated as code, not text data) to be embedded within the document, or B) to have buffer overruns because of the complexity of the file types. [Special thanks to the blog post at for the summary of recent events and for his contribution of NoScript.]
Schneier's blog also pointed readers to a paper from 2002 regarding Multics, an "an operating system from the 1960s, and had better security than a lot of operating systems today" (Schneier).

From the paper on Multics:
"Multics also avoided many of the current buffer overflow problems through the use of three hardware features. First and most important, Multics used the hardware execute permission bits to ensure that data could not be directly executed. Since most buffer overflow attacks involve branching to data, denying execute permission to data is a very effective countermeasure. Unfortunately, many contemporary operating systems have not used the execute permission features of the x86 segmentation architecture until quite recently [17].

Second, Multics virtual addresses are segmented, and the layout of the ITS pointers is such that an overflow off the end of a segment does not carry into the segment number portion. The net result is that addressing off the end of a segment will always result in a fault, rather than referencing into some other segment. By contrast, other machines that have only paging (such as the VAX, SPARC, or MIPS processors) or that allow carries from the page offset into the segment number (such as the IBM System/370) do not protect as well against overflows. With only paging, a system has to use no-access guard pages that can catch some, but not all references off the end of the data structure. In the case of the x86 processors, although the necessary segmentation features are present, they are almost never used, except for operating systems specifically designed for security, such as GEMSOS [32].

Third, stacks on the Multics processors grew in the positive direction, rather than the negative direction. This meant that if you actually accomplished a buffer overflow, you would be overwriting unused stack frames, rather than your own return pointer, making exploitation much more difficult." [Boldface and italics are mine]
Amazing. Three features that most modern OSes still do not have. Note that the "first and most important" feature is that executable code is tagged with the execute bit. While that is not pure separation of code and data, it is an excellent start because it does at least distinguish between with memory objects are code and which are just data. Hence, a char/string based buffer overflow could not result in a remote code execution scenario because the object would not have the execute bit flipped.

To be fair, some OSes have limited support for NX (No Execute) bits (which if you're smart you'll catch that to be "black lists" not "white lists" like Multics uses), but the implementation's quality and thoroughness is typically limited to support from the CPU architecture employed. From the list, though, it looks like a fair number of the 64 bit CPUs are well supported.

Windows Vista will support NX (along with ASLR), but there may be some caveats, such as the typical requirement of vendors to opt-in to use the feature. From AMD:
"For NX to be applied to a given executable, three conditions must be met. First, the processor has to support NX. As mentioned, any AMD64 processor will fill the bill here. Second, EVP support has to be on globally, which will be true for all 64-bit Vista builds and all 32-bit Vista builds unless NX support is explicitly switched off with a boot configuration option. And finally, Vista has to mark all of the program's non-code pages with the NX flag, which is determined by the operating environment (32-bit or 64-bit Vista), boot configuration options, and the program itself."
Overall, that may make a compelling argument to switch to 64 bit architecture.

So, what's today's lesson? Either separate code from data or pay for it eternally as you penetrate and patch.

No comments: