Friday, October 24, 2008

Fuzzing and MS08-67

Yesterday was pretty exciting. I'd been looking forward to it for quite some time, as it was my turn to lead the penetration testing/exploit dev class at NYU Poly. My subject for the class is fuzzing, and the first part consisted of a lecture on fuzzing history and methodologies followed by demos of COMraider, AxMan, and a video of an ActiveX exploit. I think the students are going to have some fun with ActiveX this week :-) Next week we'll be going over SPIKE in-depth.

What made the day more special was that I got to lead such a class while the rest of the infosec world was busy either patching MS08-67, or reversing it. This bug, found being exploited in the wild, ended up being a pre-auth stack overflow in a Windows RPC service. Precisely the kind of low-hanging fruit that Microsoft's SDL initiative, which includes fuzzing, was designed to stomp out. In fact, in a post-mortem write up by Michael Howard (the man behind SDL), he says:

"I'll be blunt; our fuzz tests did not catch this and they should have."

Howard doesn't go into detail about why fuzzing didn't work, which leads me to hypothesize the following:

1. The vulnerable function wasn't fuzzed at all.
2. The vulnerable function wasn't fuzzed correctly. According to the two Stephens, passing a string like \aaa\..\..\..\f is enough to trigger the overflow in the vulnerable function (which canonicalizes paths). The overflow occurs when there are not enough directories specified in the string to match the number of ..'s.

If the fuzzing engine used to test this function was not aware of the expected format of the string, it could have just passed in large string of A's, or perhaps a long string of random characters. Since such data would not be a valid path that requires canonicalization, the overflow would not occur, and would go undetected.

The lesson here is to think carefully about fuzzing strategies. It is not unreasonable to send a large string of static or random characters while fuzzing a target of an unknown code base. However, in this case we are talking about white-box fuzzing, since MS was fuzzing their own code. The fuzzer should have been given some knowledge of the data expected by the function. It would have been trivial to create fuzz strings of mangled and malformed paths that would have triggered this bug. The problem is simply that this didn't happen (atleast, not when MS fuzzed it).