Configuring IIS Directory Security through ASP.NET

As a developer, one of the most frustrating things to contend with is the case where you spend countless hours building the perfect solution, debugging and testing and fixing until there’s not a single issue left (ha!), and then finally deploying to a production server just to see your baby crash and burn!  This is particularly common when deploying web applications, and it doesn’t make it any easier when server admins guard their machines so fanatically that us developers aren’t allowed to see so much as a stack trace.

One of the best ways to avoid this scenario is to minimize the amount of configuration that must be performed on the server to install your application.  Traditionally, this was pretty tough to do, but with the introduction of IIS 7, a pretty amazing array of settings can be controlled through web.config files.  This includes, of course, directory security.

Let’s say you’ve built a nice little web site for a new client that has a bit of ASP.NET through in.  There are some XML files in a ‘data’ directory that your code needs but shouldn’t be available through the browser.  You’ve also written a back-end to be used by your client that shouldn’t be exposed to the general public.  This is a pretty typical scenario.  Traditionally, you’d deploy the web site, add the back-end files to a sub-directory called ‘admin’, and then use IIS’s directory security to deny anonymous access to the sub-directory.  Finally, you’d deny all access to the ‘data’ directory. This works.  But let’s look at the problems:

  1. Manual server configuration is required.  Is there someone around able and willing to do this?  Often, there isn’t.  In shared hosting environments, this can be particularly troublesome.
  2. Deployment considerations change depending on your platform.  This sucks.
  3. Permissions suck.  Between file permissions, share permissions, IIS permissions, user accounts, and more, it’s pretty common for things to go mysteriously wrong.
  4. What if somebody forgets?  What if a server is rebuilt, and the guy doing the rebuilding doesn’t know about locking down your special folders?  These are not scenarios you want to consider.
  5. It’s just not pretty.

Luckily, IIS 7 and ASP.NET bring us a better way.  Open your web.config file, find the <system.web> section, and add this to it:

<deny users="?" />

Now try browsing the site.  You should find that IIS now asks you to log in (or will automatically do so through Windows Authentication).  What’s happening here?  Well, it’s quite simple, really.  You just told ASP.NET to deny access to anonymous users.  Of course, this is great for controlling access site-wide, but what if you want to lock down just one directory?

Many people don’t realize this, but ASP.NET actually checks each directory for web.config files, not just the root.  Any settings specified in a directory’s web.config file apply only to that directory (and it’s children).  Some settings can only be set in the root, but many can be set anywhere.  Security is one of these.  So, let’s say you want to lock down your ‘admin’ directory.  Just add this to a new web.config file and place it in your ‘admin’ folder:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration>

Want to secure your data directory, too?  Here’s how to prevent all access to a folder:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<authorization>
<deny users="*" />
</authorization>
</system.web>
</configuration>

Simple as that!  Now, your site permissions will be included in the site’s files themselves.  Just e-mail your friendly server admin a zip file and enjoy your weekend.

But Wait…!

There’s a catch.  There’s always a catch.

This works perfectly under Visual Studio’s development server.  This will also work just fine under IIS, so long as your site only includes .ASPX and other ASP.NET files.  But, if you happen to use any other file (such as, oh, a JPG image, CSS file, or ZIP file), IIS will ignore your carefully-authored security settings and just hand out everything to everyone.  What the hell?

Don’t blame ASP.NET.  ASP.NET has nothing to do with it.  In fact, that’s exactly the problem.  For static file types, IIS just hands them out without invoking .NET (and hence without consulting your .NET-based security settings).  This makes sense… why slow things down by running a bunch of managed code when you don’t have to?  We’re just serving static files, right?

To fix this problem, you need to configure IIS to run all requests through .NET.  Open web.config (the one in your site’s root) and look for the <system.webServer> section.  Add this to it:

<modules runAllManagedModulesForAllRequests="true">

Note that if this section already exists (which is pretty likely), all you need to do is change <modules> to <modules runAllManagedModulesForAllRequests="true">.

Finally, you might want to retest your site.  You’ll now be getting requests for all file types, regardless of whether the file exists, which might expose bugs you didn’t catch before.

There’s More!

One final bit of help you might appreciate… the ASP.NET Configuration tool built into Visual Studio (check the Project menu) is actually built to help manage site security in exactly this way.  This gives you a nice web-based UI you can use to configure things rather than hand-edit XML yourself.  Just go to Security and look for Access Rules.

Enjoy!

4 comments:

  1. Can you please help me fix the 404 page in my IIS directory? I'm getting tired of writing the wrong codes.

    Shared Hosting

    ReplyDelete
  2. This code has done great change in my site, . Thanks for sharing the configuration codes in IIS.

    Reseller Hosting Services

    ReplyDelete
  3. @enkode......perhaps YOU did something wrong then...

    ReplyDelete


Copyright © 2010 Paul Guenette and Matthew Sleno.