September 2010 Blog Posts

UrlScan Broke My Blog (And How I Fixed It)

By now, you’re probably aware of a serious ASP.NET Vulnerability going around. The ASP.NET team has been working around the clock to address this. Quite literally as last weekend, I came in twice over the weekend (to work on something unrelated) to find people working to address the exploit.

Recently, Scott Guthrie posted a follow-up blog post with an additional recommended mitigation you should apply to your servers. I’ve seen a lot of questions about these mitigations, as well as a lot of bad advice. The best advice I’ve seen is this - if you’re running an ASP.NET application, follow the advice in Scott’s blog to the letter. Better to assume your site is vulnerable than to second-guess the mitigation.

In the follow-up post, Scott recommends installing the handy dandy UrlScan IIS Module and applying a specific configuration setting. I’ve used UrlScan in the past and have found it extremely useful in dealing with DOS attacks.

However, when I installed UrlScan, my blog broke. Specifically, all the styles were gone and many images were broken. It took me a while to notice because of my blog cache. It wasn’t till someone commented that my new site design was a tad bit bland, that I hit CTRL+F5 to hard refresh my browser to see the changes.

I looked at the URLs for my CSS and I knew they existed physically on disk, but when I tried to visit them directly, I received a 404 error with some message in the URL about being blocked by UrlScan.

I opened up the UrlScan.ini file located:

%windir%\system32\inetsrv\urlscan\UrlScan.ini

And started scanning it. One of the entries that caught my eye was this one.

AllowDotInPath=0         ; If 1, allow dots that are not file
                         ; extensions. The default is 0. Note that
                         ; setting this property to 1 will make checks
                         ; based on extensions unreliable and is
                         ; therefore not recommended other than for
                         ; testing.

That’s when I had a hunch. I started digging around and remembered that I have a custom skin in my blog named “haacked-3.0”. I viewed source and noticed my CSS files and many images were in a URL that looked like:

http://haacked.com/skins/haacked-3.0/style/foo.css

Aha! Notice the dot in the URL segment there?

What I should have done next was go and rename my skin. Unfortunately, I have many blog posts with a dot in the slug (and thus in the blog post URL). So I changed that setting to be 1 and restarted my web server. There’s a small risk of making my site slightly less secure by doing so, but I’m willing to take that risk as I can’t easily go through and fix every blog post that has a dot in the URL right now.

So if you’ve run into the same problem, it may be that you have dots in your URL that UrlScan is blocking. The best and recommended solution is to remove the dots from the URL if you are able to.

Overriding a .svc Request With Routing

I was drawn to an interesting question on StackOverflow recently about how to override a request for a non-existent .svc request using routing.

One useful feature of routing in ASP.NET is that requests for files that exist on disk are ignored by routing. Thus requests for static files and for .aspx and .svc files don’t run through the routing system.

In this particular scenario, the developer wanted to replace an existing .svc service with a call to an ASP.NET MVC controller. So he deletes the .svc file and adds the following route:

routes.MapRoute(
  "UpdateItemApi",
  "Services/api.svc/UpdateItem",
  new { controller = "LegacyApi", action = "UpdateItem" }
);

Since api.svc is not a physical file on disk, at first glance, this should work just fine. But I tried it out myself with a brand new project, and sure enough, it doesn’t work.

Baffling!

So I started digging into it. First, I looked in event viewer and saw the following exception.

System.ServiceModel.EndpointNotFoundException: The service '/Services/api.svc' does not exist.

Ok, so there’s probably something special about the .svc file extension. So I opened up the machine web.config file located here on my machine:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config

And I found this interesting entry within the buildProviders section.

<add extension=".svc" 
  type="System.ServiceModel.Activation.ServiceBuildProvider, 
  System.ServiceModel.Activation,
  Version=4.0.0.0, Culture=neutral, 
  PublicKeyToken=31bf3856ad364e35" 
/>

Ah! There’s a default build provider registered for the .svc extension. And as we all know, build providers allow for runtime compilation of requests for ASP.NET files and occur very early in response to a request.

The fix I came up with was to simply remove this registration within my application’s web.config file.

  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <buildProviders>
        <remove extension=".svc"/>            
      </buildProviders>
    ...

Doing that now allowed my route with the .svc extension to work. Of course, if I have other .svc services that should continue to work, I’ve pretty much disabled all of them by doing this. However, if those services are in a common subfolder (for example, a folder named services), we may be able to get around this by adding the build provider in a web.config file within that common subfolder.

In any case, I thought the question was interesting as it demonstrated the delicate interplay between routing and build providers.