Introduction
When creating a data-driven Web site using Microsoft Access, it is important to take good care
of the Access database file (the .mdb file). If you place the .mdb file
in a Web accessible directory on the Web server, anyone who knows (or can guess) the name of the
Access database file can download the file via their Web browser. This can be an especially
perilous situation if the Access database file contains sensitive information, such as passwords,
payment information, or other personal, private data.
There are a couple of ways to protect an Access database file (or any arbitrary file). The
most straightforward way is to place it in a non-Web accessible directory. Many Web hosts,
for example, have a special database folder that provides the necessary
read/write access requires for an Access database, but is not Web accessible.
(When using Access, you will get an "Operation must use an updateable query" error unless the .mdb
file exists in a directory with read/write permissions for the account accessing the
file. For a more thorough discussion on this be sure to read the FAQ Why
am I getting 'Operation must use an Updateable Query' error?)
In this article we will examine how to use ASP.NET to protect Access database files, or files
with an arbitrary extension.
Understanding How IIS and ASP.NET Work
When a request comes into Microsoft's IIS Web server its extension is examined and, based on
this extension, the request is either handled directly by IIS or routed to an ISAPI extension.
An ISAPI extension is a compiled class that is installed on the Web server and whose responsibility
it is to return the markup for the requested file type.
By default, IIS handles the request, and simply returns the contents of the file requested.
This makes sense for static files, like images, HTML pages, CSS files, external JavaScript
files, and so on. For example, when a request is made for a .html file, IIS
simply returns the contents of the requested HTML file.
For files whose content is dynamically generated, the ISAPI extension configured for the file
extension is responsible for generating the content for the requested file. For example,
a Web site that serves up classic ASP pages has the .asp extension mapped to
the asp.dll ISAPI extension. The asp.dll ISAPI extension executes
the requested ASP page and returns its generated HTML markup. If your Web site serves up
ASP.NET Web pages, IIS has mapped the .aspx to aspnet_isapi.dll,
an ISAPI extension that starts off the process of generating the rendered HTML for the
requested ASP.NET Web page.
The aspnet_isapi.dll ISAPI extension is a piece of unmanaged code. That is,
it is not code that runs in the .NET Framework. When IIS routes the request to the
aspnet_isapi.dll ISAPI extension, the ISAPI extension routes the request onto
the ASP.NET engine, which is written in managed code - managed code is code that runs in
the .NET Framework.
The ASP.NET engine is strikingly similar to IIS in many ways. Just like IIS has a directory mapping file
extensions to ISAPI extensions, the ASP.NET engine maps file extensions to HTTP handlers. An
HTTP handler is a piece of managed code that is responsible for generating the markup for a particular file
type. For example, ASP.NET Web pages are rendered by the PageHandlerFactory;
the SOAP responses of Web services are generated by the WebServiceFactoryHandler. The
PageHandlerFactory knows how to render the HTML markup of an ASP.NET Web page; the
WebServiceFactoryHandler knows how to accept incoming SOAP requests, invoke the proper
Web service method, and return the response in a properly formatted SOAP response.
For More Information on IIS and ASP.NET...
For more a good overview on how ASP.NET and IIS work in serving ASP.NET Web pages be sure to read
How ASP.NET Web Pages are Processed on the Server, an earlier article of mine.
Michele Leroux Bustamante provides a much more in-depth
examination of ASP.NET and IIS in her article, Inside
IIS & ASP.NET.
Examining the HttpForbiddenHandler
ASP.NET Web applications have their configuration information specified via an XML-formatted file,
Web.config. Web.config can contain information like:
Database connection strings,
Information on how users are authenticated, which might include user and password information,
Information on authorization, and
Other potentially sensitive information.
Clearly, allowing any Web visitor to view the contents of an ASP.NET Web application's Web.config
file could be disastrous. Take a moment, though, to try to access the contents of an ASP.NET application's
Web.config file. Here, you can try to access the Web.config file here on 4Guys -
http://aspnet.4guysfromrolla.com/Web.config.
When you try to view the file you get back a page that says: This type of page not served.
How did a request to Web.config return a specialized page rather than the contents of the
Web.config file? Well, in IIS files with the .config extension are mapped to the
ASP.NET ISAPI extension. The ASP.NET engine, then, maps requests to .config files to
the HttpForbiddenHandler HTTP handler. The HttpForbiddenHandler HTTP handler
returns the HTML you see when visiting the Web.config file through your browser.
We've just seen how ASP.NET uses the HttpForbiddenHandler HTTP handler to protect .config
files - it also uses this approach to protect .cs, .vb, .webinfo,
.vbproj, .csproj, .resx, and others. Similarly, we can use this
technique to protect Access database files (.mdb files), or any arbitrary file extension. In
the next section we'll look at the steps necessary to protect a given file extension.
Protecting .mdb Files
Let's look at how to protect Access database files using the same techniques ASP.NET uses to protect
.config files. To accomplish this we must perform the following two steps:
Configure IIS so that .mdb files are mapped to the ASP.NET ISAPI extension
Configure ASP.NET so that .mdb files are mapped to the HttpForbiddenHandler HTTP handler
To configure IIS to map .mdb files to the aspnet_isapi.dll ISAPI you will need
access to Web server. Log on to the Web server and open the IIS Administration dialog, which is available
through the Administrative Tools section. Next, right-click on the Web site you want to configure and
choose Properties. This will display the Web Site Properties dialog box. Navigate to the Home Directory
tab and click the Configuration button. This will display the Application Configuration dialog box, which
is shown below.
Windows NT/2000/XP
Windows 2003
To add a mapping, click the Add button. This will display a new dialog box that allows you to enter
the ISAPI extension that should execute when a request comes in for a specific file extension. (You can
also specify if this mapping should apply to all incoming HTTP requests (GET and POST), or to a specific
HTTP verb.)
So, to add a mapping for .mdb files, enter .mdb as the extension and choose the
ISAPI aspnet_isapi.dll ISAPI extension. (This should be in the directory
$WINDOWS_DIR$\Microsoft.Net\Framework\$VERSION$.)
Now that we have configured IIS to map .mdb files to the ASP.NET ISAPI extension, we're ready to
tackle our final step: specifying that our Web application should map .mdb files to the
HttpForbiddenHandler HTTP handler. To accomplish this, simply add the following lines to the
Web application's Web.config file:
This needs to be placed inside the <system.web> element. With this addition, when
.mdb files are requested from the specific Web application, a This type of page is not
served error message will be returned.
Adding the above <httpHandlers> section to a Web.config file configures
that .mdb files are mapped to the HttpForbiddenHandler HTTP handler just for
that Web application. If you want to apply this mapping to all ASP.NET Web applications on the
Web server, simply add <add verb="*" path="*.mdb" type="System.Web.HttpForbiddenHandler" />
to the machine.config file's <httpHandlers> section. (The
machine.config file is located in the $WINDOWS_DIR$\Microsoft.Net\Framework\$VERSION$\CONFIG
directory.)
Conclusion
In this article we saw how to use ASP.NET HTTP handlers to protect files with a certain extension. Accomplishing
this involves two steps: first, the file extension in IIS needs to be mapped to the ASP.NET ISAPI extension;
next, the ASP.NET engine needs to be configured to map the same extension to the HttpForbiddenHandler
HTTP handler. Realize that both of these two steps are vital - if you forget to map the extension in IIS to the
ASP.NET ISAPI extension, then the ASP.NET engine will not be invoked when a file with the forbidden extension
is accessed. If you map the file extension correctly through IIS, but forget to perform the mapping in the
appropriate ASP.NET configuration file, the ASP.NET engine will simply return the contents of the file.