MS08-078 and the SDL

MS08-078 and the SDL

Rate This
  • Comments 8
Hi, Michael here.

Every bug is an opportunity to learn, and the security update that fixed the data binding bug that affected Internet Explorer users is no exception. 

The Common Vulnerabilities and Exposures (CVE) entry for this bug is CVE-2008-4844.

Before I get started, I want to explain the goals of the SDL and the security work here at Microsoft. The SDL is designed as a multi-layered process to help systemically reduce security vulnerabilities; if one component of the SDL process fails to prevent or catch a bug, then some other component should prevent or catch the bug. The SDL also mandates the use of security defenses whose impact will be reflected in the "mitigations" section of a security bulletin, because we know that no software development process will catch all security bugs. As we have said many times, the goal of the SDL is to "Reduce vulnerabilities, and reduce the severity of what's missed."

In this post, I want to focus on the SDL-required code analysis, code review, fuzzing and compiler and operating system defenses and how they fared.

Background

The bug was an invalid pointer dereference in MSHTML.DLL when the code handles data binding. It's important to point out that there is no heap corruption and there is no heap-based buffer overrun!

When data binding is used, IE creates an object which contains an array of data binding objects. In the code in question, when a data binding object is released, the array length is not correctly updated leading to a function call into freed memory.

The vulnerable code looks a little like this (by the way, the real array name is _aryPXfer, but I figured ArrayOfObjectsFromIE is a little more descriptive for people not in the Internet Explorer team.)

int MaxIdx = ArrayOfObjectsFromIE.Size()-1;

for (int i=0; i <= MaxIdx; i++) {

     if (!ArrayOfObjectsFromIE[i])

           continue;

      ArrayOfObjectsFromIE[i]->TransferFromSource();

      ...

}

Here's how the vulnerability manifests itself: if there are two data transfers with the same identifier (so MaxIdx is 2), and the first transfer updates the length of the ArrayOfObjectsFromIE  array when its work was done and releases its data binding object, the loop count would still be whatever MaxIdx was at the start of the loop, 2.

This is a time-of-check-time-of-use (TOCTOU) bug that led to code calling into a freed memory block. The Common Weakness Enumeration (CWE) classification for this vulnerability is CWE-367.

The fix was to check the maximum iteration count on each loop iteration rather than once before the loop starts; this is the correct fix for a TOCTOU bug - move the check as close as possible to the action because, in this case, the array size might change.

Code Analysis and Review

Memory-related TOCTOU bugs are hard to find through code review; we teach TOCTOU issues, and we teach memory corruption issues, and issues with using freed memory blocks; but we do not teach memory-related TOCTOU issues. We will update our training to address this.

Our static analysis tools don't find this because the tools would need to understand the re-entrant nature of the code.

Fuzz Testing

In theory, fuzz testing could find this bug, but today there is no fuzz test case for this code. Triggering the bug would require a fuzzing tool that builds data streams with multiple data binding constructs with the same identifier. Random (or dumb) fuzzing payloads of this data type would probably not trigger the bug, however.

Defenses

There is a plethora of defenses available on various versions of Windows, but only a couple came into play owing to the nature of the code.

-GS

As mandated by the SDL, the code is compiled with -GS to detect some forms of stack-based buffer overruns at runtime, but it's moot because this is not a stack-based buffer overrun.

ASLR and NX

Even though Windows Vista and Windows Server 2008 have both ASLR and NX enabled by default, Internet Explorer 7 does not opt-in to these defenses owing to compatibility issues with many common applications. Internet Explorer 8 enables these defenses by default, but an attack could be mounted by calling a component that does not use these defenses, and then by using an attack technique known as heap-spraying get the attacker's code into the non-ASLR and non-NX memory. This is why it's so important to build components for Windows that use all the available Windows defenses. Matt Thomlinson and I wrote an article on this subject, and David LeBlanc and I wrote Writing Secure Code for Windows Vista that covers the subject in much more detail.

Heap Termination on Corruption

IE7 and IE8 both use the SDL-required process termination if the heap is corrupted (you can read more about this here.) But there is technically no heap corruption, so the defense does not come into play in this instance.

Internet Explorer 7 and 8 Protected Mode

On Windows Vista and Windows Server 2008, this is a major defense that comes into play against the currently circulating exploits. When the exploit code runs, it's running at low integrity because IE runs at low integrity, and this means the exploit code cannot write to higher integrity portions of the operating system, which is just about everywhere!

For our server platforms, Windows Server 2003 and Windows Server 2008, Internet Explorer Enhanced Security Configuration also prevents the exploit from working because the vulnerable code is disabled.

How was the bug found?

We really don't know how the bug was found, but some of the security people in Internet Explorer and the Trustworthy Computing Security teams suggest that the bug was either "stumbled upon" or found through directed fuzzing. The finder could spend as long as he or she wanted to find this one bug. This is one of the things that makes security hard - security is a highly asymmetric problem: software developers must get the code right 100% of the time in a very short amount of time, while attackers can spend as long as they want to find one bug.  This isn't an excuse; it's a fact of life

Summary

I think this bug is a great example of "you will never get the code 100% right, so multiple defenses are critical." As you can see from this post, many defenses in Windows did not come into play, but all it takes is one defense to help stop or reduce the chance that an exploit will succeed, and in the case of Windows Vista and Windows Server 2008, Internet Explorer's Protected Mode was that defense.

If there is one other lesson from this, it's that we, the software industry, need to work harder to make sure applications take advantage of the defenses offered in Windows today.

Credits

Big thanks to Chengyun Chu, Jonathan Ness, Adam Shostack, Bronwen Matthews, Mike Reavey and Steve Lipner for their valuable edits and input to this post.

I also want to thank the Internet Explorer team and the Microsoft Security Response Center team for such a rapid turn-around under incredible pressure. A job well done.
Comments
  • PingBack from http://infosecphils.wordpress.com/2008/12/19/now-its-firefoxs-and-operas-turn/

  • Microsoft Corp.&#39;s developers missed a critical bug in Internet Explorer because they weren&#39;t

  • Este post esta adelantado a su tiempo&#160; - porque tenia que salir antes otro post - , pero la situación

  • "The fix was to check the maximum iteration count on each loop iteration rather than once before the loop"

    But does this actually fix the issue or just reduce the time window in which it can be exploited? Surely the correct fix is to make the check and action atomic with respect to the array?

  • Actually looking again the fix is fine; I thought the array update was happening in another thread.

    Though surely Size() is 2 at the start, so MaxIdx is 1?

  • a {color : #0033CC;} a:link {color: #0033CC;} a:visited.local {color: #0033CC;} a:visited {color : #800080;}

  • Hello, Michael here... Over the last couple of years, I've released information about various Microsoft

  • I agree with Kieran on this, moving the check closer will only shorten the time window but not prevent the exploit form happening.

    Another correct fix, in addition to what Kieran suggested, would be to make a copy of array and act on it. I believe that's how CreateFile works, where it makes a copy of file name parameter before doing anything with it.

Page 1 of 1 (8 items)
Leave a Comment
  • Please add 6 and 8 and type the answer here:
  • Post