Protecting non-ASP.NET resources with ASP.NET 2.0

by Dominick Baier

Related link: http://www.leastprivilege.com/ProtectingNonASPNETResourcesWithASPNET20.aspx



A common problem I see in audits is, that people throw all kinds of files into their ASP.NET vdir (like .xml, .mdb etc) and just assume that these files will be protected by ASP.NET authentication & authorization. This is not the case.


IIS passes all ASP.NET related requests (.aspx, .asmx etc) to the ASP.NET AppDomain, everything else is served directly by IIS. If you want that your static files (or .asp files - more on that later) are handled by ASP.NET and its security system, you have to configure IIS to pass these requests to ASP.NET, too. This is done in the configuration settings of you IIS web application. In the script mappings dialog you configure which extensions are passed to which ISAPI extension - if you want to add specific extensions, add a new script mapping in the upper half of the dialog (have a look at which .dll the .aspx extension is configured for and use the same one for your static file).


Another option is to map every extension to ASP.NET. This is done in the wildcard mapping section in the lower part of the dialog. Just add the aspnet_isapi.dll here and all requests will be forwarded to ASP.NET. Be sure to uncheck "verify if file exists", otherwise "virtual" URLs like WebResource.axd won't work anymore.


By configuring a HttpForbiddenHandler you can now selectively deny files from being accessed via the browser.


<httpHandlers>


      <add path="*.xml" verb="*" 


        type="System.Web.HttpForbiddenHandler" validate="True" />


</httpHandlers>



Well, before ASP.NET 2.0 this was not very practical because now the ASP.NET runtime has to serve all requests which resulted in a major performance degradation. In ASP.NET 2.0 the underlying architecture has changed to provider better support for this scenario. All unknown file extensions are now handled by a class called DefaultHttpHandler.


<add path="*" verb="GET,HEAD,POST" type="System.Web.DefaultHttpHandler" validate="True" />


This special handler accomplishes, that requests for static (or non-ASP.NET files) only pass the "front half" of the HTTP pipeline (including the important Authenticate and AuthorizeRequest events). Right before the point where page execution would normally begin, ASP.NET bounces the request back to IIS. This is much faster and gives you the best of both worlds. You can use the ASP.NET security infrastructure (e.g. forms authentication) to protect the files but you don't lose the performance of IIS request processing.


If you need more control, you can derive from DefaultHttpHandler and customize its behaviour. If you override the OverrideExecuteUrlPath method, you can modify the request path that gets handed back to IIS. You can also add new HTTP header to the request by adding entries to the ExecuteUrlHeader collection. This enables you e.g. to protect a classic ASP application with ASP.NET forms authentication and you can pass the user and role information via headers from ASP.NET to ASP.


Warning: Be sure to validate and authenticate the headers you pass with ExecuteUrlHeader, e.g. by adding a MAC using a secret that is shared between ASP and ASP.NET (HMACSHA1 would be a possibility).