Secure Resource and Document Files
Configure IIS and ASP.NET to protect resource files with the same access control constraints as the rest of your app.
October 30, 2009
asp:feature
LANGUAGES: All .NET Languages
ASP.NET VERSIONS: 1.0 | 1.1
Secure Resource and Document Files
Configure IIS and ASP.NET to protect resource files withthe same access control constraints as the rest of your app.
By Brian Noyes
A common question when developing ASP.NET applications is,"How do you secure files such as images, documents, audio files, XML files, andother resources that are part of your Web app?" The answer depends on what kindof security you are using for the rest of your ASP.NET application.Understanding the solutions requires a little understanding of the steps anHTTP request goes through when IIS and ASP.NET service it. For brevity, I amgoing to refer to these files as resource files. By this I mean any kind offile (image, audio, video, document, PDF file, source, and so on) that is notpart of the pages that your application URLs usually address, but does residein your Web application's folders.
The processing chain that occurs from when a request comesinto the server until when it goes back out to the client as a response isoften called the HTTP pipeline. I am assuming you are using IIS for thisexplanation. Although ASP.NET could be configured to work with other Webservers, the vast majority of deployed applications use IIS, so that is all Iwill focus on here.
Peer Down the HTTPPipeline
The first thing that occurs when an HTTP request isreceived is that IIS must decide what to do with it. It does this by looking atthe URL and checking the file extension at the end of it. Based on this fileextension, IIS will decide whether it knows how to service requests for thatkind of file, or whether it should pass it off to one of the ISAPI extensionsconfigured in IIS. For example, if a request for an ASP file comes in, IIS willsee that it has an ISAPI extension (asp.dll) registered to handle requests forfiles of that type. It then hands the request off to that extension and is outof the loop until the extension returns the response. IIS knows how to servicerequests for common Web files, such as HTML and image files, so if no ISAPIextension is registered to handle requests for those types of files, IIS willsimply return the file as a stream.
So how does ASP.NET get in the game? Well, ASP.NET has anISAPI extension registered in IIS as well, aspnet_isapi.dll, and it is thatextension that is responsible for handing off requests for ASP.NET pages, Webservices, and resources to the ASP.NET worker process. When you install .NET,the installer registers the ISAPI extension and associates a bunch of known.NET file types (such as ASPX, ASCX, CS, VB, CONFIG, and so on) with theASP.NET ISAPI extension in IIS so that requests for those file types will getpassed off to ASP.NET. From there the ASP.NET worker process figures out whatto do with the request based on which HTTP handlers are registered for thatfile type in .NET, passing the request through any configured HTTP modules onthe way (see Figure 1).
Figure 1. The HTTP requestprocessing pipeline in .NET takes any requests routed to ASP.NET from IIS andhands them to the appropriate HTTP handler endpoint based on the sections in the web.config and machine.config files.
The built-in registrations for ASP.NET are buried in yourmachine.config file under the element in a element. There are a bunch of handlers that ship with the.NET Framework, and it is these handlers that act as endpoints for requests toenable a lot of the processing, such as the processing of ASPX pages and Webservices that most people just think of as part of the ASP.NET runtime. You canoverride and supplement the handlers configured in machine.config by adding an section in your application web.config file.
For a little more information on the HTTP pipeline andwhat HTTP modules do in that processing chain, see my article ExtendASP.NET With HTTP Modules.
The next thing to understand is how to secure an ASP.NETapplication in general. That is a whole topic unto itself, so I will have toassume you are familiar with the Windows, Forms, and Passport authenticationoptions for securing an ASP.NET application. The steps discussed in the rest ofthis article focus mainly on either Forms or Passport authentication. Whetherthey apply to Windows authentication or not depends on whether the files youare interested in protecting are mapped to ASP.NET in IIS.
If you secure an ASP.NET application with Windows authenticationand a request is made for a file that resides within your application that isnot mapped to ASP.NET (such as a bitmap, JPEG, WAV, or XML file), IIS decideswhether to serve that file up based on the Access Control Lists (ACLs) for thefile and the authenticated identity of the logged on user. The files will beautomatically protected at the same level as the rest of your applicationunless you specifically relax the ACLs. If you map the files you want toprotect to ASP.NET with Windows authentication, IIS will step out of the wayand leave it up to ASP.NET to do the access checks. However, those checks willstill be based on the ACLs and the logged on user if you are using Windowsauthentication.
If you are using Forms or Passport authentication, filesnot mapped to ASP.NET can be served up to even non-authenticated users, evenwhen they reside in the folders of your ASP.NET secured application. So if youwant to protect access to resource files that are part of your application whenusing Forms or Passport authentication, the first step is to get them mappedinto ASP.NET.
It's All AboutConfiguration
Once you understand the processing chain and the way IISmakes decisions about what ISAPI extension is responsible for serving a requestfor a file, the steps to securing resource files become more clear. The firstthing is to get the file extensions for the files you want to protect mapped toASP.NET. To do this, you bring up the IIS Management Console and select thevirtual directory or root for your Web application. You then select Properties,and in the Directory tab, press the Configuration button toward the bottom.That takes you to the Application Configuration dialog, which is where themappings I keep talking about are configured in IIS (see Figure 2).
Figure 2. IIS decides where to sendrequests based on mappings between file extensions and ISAPI extensions in theApplication Configuration settings.
The easiest way to add a file extension that is mapped toASP.NET, such as ASCX, is to select Edit for one of the file extensions that isalready mapped to ASP.NET, and copy the path to the ISAPI extension executableusing Ctr-Ins (Ctrl-C/Ctrl-V doesn't work in this dialog for some reason). Thencancel out of editing that one and add a new one for the file extension youwant to map by pasting the executable path in with Shift-Ins and entering thefile extension (for example, BMP), and clicking on OK (see Figure 3).
Figure 3. To add a mapping for afile extension to ASP.NET, you add an Application Extension Mapping from theApplication Configuration dialog.
Once you have done that, all subsequent requests for URLsending in that file extension for that Web application will pass the request toASP.NET for handling. If the ASP.NET application is configured forauthentication, then any access to files of that type will be authenticated byASP.NET, just like it's done in the rest of the application.
There is one other scenario you may need to accommodate.What if the kind of file you want to expose is already mapped to ASP.NET, andyou want to expose it in your authenticated ASP.NET app, but it is beingblocked by the machine.config file or web.config file at the site level becausethere is a handler that denies access to the file? For example, by default,source code files are protected and cannot be viewed through the browser, evenby authenticated users. It works like this because there is an entry in themachine.config file section that looks like this:
type="System.Web.HttpForbiddenHandler"/> The HttpForbiddenHandler blocks access to any files it ismapped to by the specified path in the config file entry. Your systemadministrator very well may have added entries like that at a machine level toprohibit access to XML files, documents, or any number of other file types.However, it may actually make sense to expose those file types in your app,depending on its purpose. If that is the case, you can override the handlersfrom machine.config by either removing or replacing them at the applicationlevel. So, for example, if you were building a site that allowed authenticatedusers to view source code files for development purposes, you can remove thatforbidden handler at the application level by adding a section such as this oneto your web.config: ... Also remember that you can enforce role-based security onspecific files and folders using ASP.NET, so you might want to add alocation-based authorization tag to allow only people in a developer role toview these files. See the docs on configuring authorization at the file levelfor more info on that (see the Resources section at the end of this article). Don't Forget AboutPerformance Just because you can do something doesn't alwaysmean you should do it. Although it issimple to configure IIS and ASP.NET so that resource files are protected underthe same authentication and authorization constraints as the rest of your app,you shouldn't just blindly do this. Do it only if it is really necessary. Thereis a minor performance hit for the extra steps of passing the request for aresource off to ASP.NET, having ASP.NET check to see if access is granted, andthen having ASP.NET to return the resource to IIS. If you have a page composedof hundreds of tiny images that comprise the borders and graphics layout foryour site, ASP.NET is going to have to do an awful lot of work to protect andserve the images that you really don't need protection anyway. On the otherhand, if you have a subscription-based image library, you definitely won't wantthose images accessible to unauthenticated users. So just be smart aboutapplying this concept. You might want to serve up the images you don't careabout protecting from a separate virtual directory that does not have imagefiles mapped to ASP.NET. Then you would put only those files you really need toprotect within your application folders, and configure things as I've discussedin this article. BrianNoyes is a software architect with IDesign, Inc. (http://www.idesign.net), a .NET-focusedarchitecture and design consulting firm. Brian specializes in designing andbuilding data-driven distributed Windows and Web applications. He has more than12 years of experience in programming, engineering, and project management, andis a contributing editor and writer for C#PRO,asp.netPRO, and other publications.Contact him at mailto:[email protected]. Resources9Steps to Secure Forms Authentication by Beth Breidenbach. AuthenticateUsers with Microsoft Passport by Steven Turley.
About the Author
You May Also Like