Fixing hash DoS good and proper (and breaking ASafaWeb)

Remember hash DoS? This was that very clever yet equally nasty little attack which meant that if you formatted the parameters in a post request juuuuust right you could take down an ASP.NET website with a mere single request. Bugger.

This made for a rather unpleasant Christmas and New Year period for a number of people at Microsoft as well as sys admins the world over. Microsoft had rapidly released a the MS11-100 critical patch or in other words, the stop-what-you’re-doing-and-install-it-RIGHT-NOW patch.

But it wasn’t really a patch per se in that it didn’t fix the underlying vulnerability which was related to hash collisions. Instead, it stopped an attacker from posting more than 1,000 form parameters to a website so think of it more as a pre-emptive defence rather than a fix.

I also had a bit of a rush around this time because I wanted to get ASafaWeb scanning for the presence of the patch. Oftentimes developers do not have direct visibility into the patch level of the infrastructure they’re running on so I wanted a means of self-assessment. It was easy too – all I had to do was post 1,001 form parameters and if the website returned an error, the patch was installed. If it didn’t then it meant the request was being processed and the patch wasn’t present. There were a couple of twists and turns (such as the request object needing to be accessed in an MVC app for it to work), but for the most part, it all went swimmingly.

Now Microsoft has gone and broken my scan – and I couldn’t be happier. Today I ran all my ASafaWeb integration tests which checks the scan results against a number of sites and suddenly my test against the deliberately insecure ASafaWeb test site at was failing. I mean the formal unit test was failing because it expected the hash DoS scan to pass (the AppHarbor infrastructure it runs on was patched very quickly), but for some reason the hash DoS scan was now failing.

The other component of the integration test that was failing was that it expected the ASP.NET version of the website to be 4.0.30319.272 yet it was coming back as 4.0.30319.17929. This is the version number you get back at the bottom of a stack trace and it includes the last segment of digits (the version returned in the X-AspNet-Version header does not). Coincidence? I think not, and here’s why:

Hashtable and Dictionary in 4.5 use randomized hash algorithm if using StringComparer.

This is very good news because what Levi is saying is that the underlying hash implementation has now been resolved hence there is no longer a need to stop excessive form parameter posts in their tracks. Good for the ASP.NET ecosystem, not so good for ASafaWeb tests!

What this now means is that detecting the risk of hash DoS is harder, much harder. But it’s not impossible and I’d like to share the process that I’ve just implemented in ASafaWeb. The main reason I want to share this is that I’d like people to pick holes in it and tell me where it can be improved.

The thing now is that there are many conditions which need to be assessed and even then, there are many circumstances which will lead to inconclusive results. Still, here’s what’s happening:

Decision tree for detecting hash DoS protection

Here are some key assumptions that may not be immediately clear:

  1. ASP.NET 4.5 is safe. Once we see version 4.0.30319.17929 present we know that the hash DoS protection is built right into the core. Problem is that you can only detect this if a stack trace can be caused or a trace.axd handler accessed.
  2. ASP.NET 4 on IIS 8 is safe. This is simply because of the previous point; .NET 4.5 ships with IIS 8. Whilst 4 versus 4.5 can’t be detected from the response header alone, 4.x can be as can the IIS version (unless they’ve been deliberately obfuscated).

The goal is to try and minimise the results that fall into the “inconclusive” category; no risk is great, a confirmed risk is also great (at least from an accuracy perspective), but there are still many scenarios that will cause an inconclusive result. For example:

  1. Not knowing the version of .NET the site is running under and not being able to cause an error by posting too many form vars.
  2. Not receiving a valid response when posting the form vars (“method not allowed” response, timeout, empty response, etc.)
  3. Site is not web forms and posting the vars doesn’t cause an error (could be MVC and the request object is being accessed)

There are probably others I should consider or could apply to improve the system and I’d love to hear this feedback. If you know your way around ASP.NET and can see holes or improvements in this, please do let me know. For now, the approach detailed above has been implemented so feel free to go and try it out at

Security .NET ASafaWeb
Tweet Post Update Email RSS

Hi, I'm Troy Hunt, I write this blog, create courses for Pluralsight and am a Microsoft Regional Director and MVP who travels the world speaking at events and training technology professionals