HOWTO: Protect non-.NET content

This is a frequently asked question - how to implement custom authentication on IIS. I am going to ramble a bit about the whole subject because this is a little pet peeve of mine...

Question:

Hi David,

I am an avid lurker on your Blog and our company posts some of your HOWTO's on out internal web. Thank you for all the good info.

We are running many websites in a server farm. All of the webs feature a mix of classic ASP and .NET content in C#. We are currently using C++ ISAPI filters to protect classic ASP content from miscreants. Authentication is done either by the ISAPI filters or by the .NET content. Credentials are checked by the ISAPI filters after authentication. We are migrating to IIS 6.0 on Windows Server 2003 but are not completely converted from IIS 5.0 on Windows 2000 Server.

Our problem is that the management of the ISAPI filters is taking too many resources. This is mainly due to the several versions of the filters (which were written in-house) and their configuration options. These options mostly have to do with DB connection strings and passthru mechanisms for content such as images, stylesheets and script files.

I would like to know if it is possible to protect clasic ASP and other non-.NET content soley with an IIS and/or .NET mechanism. Particularly IISWebFile, IISWebDirectory, IISWebVirtualDir, etc. in conjunction with web.config and machine.config settings. Can you help shed some light on this issue? Can you tell us of a way to protect web content without requiring ISAPI filters?

Answer:

Thanks for using my posts - it is exactly what I am hoping to do - provide digested information and insights that help you do something new/better with less time/money/resources. :-) But first, I have to take care of a little pet peeve of mine when it comes to this subject...

<soapbox>

By far the easiest and most secure mechanism to protect any sort of content on IIS is to use its built-in authentication protocols such as Basic/NTLM/Kerberos/Digest/Passport and built-in authorization model using NT ACLs on the NTFS FileSystem. I believe that it offers a good combination of simplicity to configure and use, secure, well-tested, and well-integrated. Active Directory adds scalable user identity management and intra-machine trust, which allows security concepts like constrained delegation to enable secure "forwarding" of user credentials to access remote resources. It is probably the most complete and commonly available security system which integrates across multiple servers seamlessly and secures both the user on the client and remote servers involved, and you get it when you choose Windows.

Unfortunately, most users do not understand security other than "I want it to be cheap, simple, and secure". Combined with the problem that Active Directory is easily misunderstood and hard to configure perfectly (security can be like that - usually, there are a million wrong ways to do something and only one secure, correct way), users often end up abandoning Active Directory for one bad reason or another. Instead, they choose to implement their own little simple, custom authentication/authorization solution that they understand and fit it into their environment... and get off to the wrong foot. Why? Because more likely than not, these solutions are either insecure in some fundamental way(s) from a security perspective (the user just does not know it... yet... since they rarely have the security/cryptography training), and even if the solution is secure, it basically ends up being a private implementation of the exact same publicly designed protocol that IIS already supports.

So, I question why anyone should ever re-invent the wheel when it comes to authentication/authorization, especially when your solution is usually less verified, less hardened, and probably built with less domain knowledege?

</soapbox>

... ok, now that I have gotten that off of my chest, let me answer your specific question.

Short Answer

If you are looking for a custom authentication solution which works with IIS5 and IIS6, applies to static files, ASP, and ASP.Net content, and does not involve ISAPI Filters, then there is no solution. The reason is simple:

  • IIS only supports three extensibility mechanisms - CGI, ISAPI Extension, and ISAPI Filter (we changed this in IIS7 by adding a new API which allows both native and managed code to be used, but that is not the point of discussion here...)
  • Prior to IIS6 only ISAPI Filter can "filter" a request without owning it
  • Custom authentication/authorization is a request processing phase, not response generation - thus it requires the ability to "filter" a request without owning it

What this means is that:

  • With an ISAPI Filter, custom authentication is always possible on any IIS version
  • It is architecturally impossible to apply ASP.Net Forms authentication on ASP content on IIS5 because ASP.Net ends up owning generating the response for ASP content, which does not work (ASP.DLL should process ASP pages).
  • It is architecturally possible on IIS6 to apply ASP.Net 2.0 Forms authentication on ASP content due to new IIS functionality allowing ISAPI Extension to "filter" a request without owning it, and ASP.Net 2.0 added support for this new functionality. To be clear, this does not work with ASP.Net 2.0 on IIS5 or ASP.Net 1.1 or IIS6 - they are both missing the necessary support.

Addendum

Ok, I am going to be brutally honest here. Please do not take it personally - I am just looking at the data and openly musing about it:

  • I do not think your problem has anything to do with ISAPI Filter management costing too much resources
  • I do not think that excluding solutions based on technology makes sense here

Why? Well, I think your real problem has to do with poorly designed ISAPI Filters that do not interact and integrate with each other cohesively to provide the comprehensive custom authentication/authorization story that you need. It is not surprising given my pet-peeve rant earlier - most people in this world should not be writing such systems. It is usually a one-off hack of some sort, and hacks beget hacks, etc... which gets ugly and complicated.

Also, deciding on solutions based on implementation technology makes no sense to me. Implementation technology does not build security; knowledgeable people do. If you cannot build the security system with ISAPI Filter, why would you be able to do it correctly with .Net or even re-leverage the built-in IIS mechanism? In other words, how does .Net or avoiding ISAPI Filter improve your situation? If you can give me the answer to that, I can probably tell you how to do it correctly with ISAPI Filter... and if you say that you have more experienced .Net developers than C++, then I will tell you that you are still doomed -- what you need are developers that understand security theory, and understanding of API is not a valid constraint.

In other words, I want to help you solve your fundamental problem. I do not believe your problem is caused by ISAPI Filters but rather by poor understanding and design, and IIS/.Net is not a solution to poor design. Learning how to build with better design (or buying implementations of better design) are the ways to solve your problem. I really do not understand what you desire in your ideal system nor what you want to do, so I cannot give any more concrete advice.

I can tell you that for a solution that has to cross over between IIS5 and IIS6 and has to protect static, ASP, and ASP.Net content, an ISAPI Filter is the only way. On IIS6 with ASP.Net 2.0, it is possible to impose ASP.Net Forms Authentication on any content type, but that requires an understanding of how IIS and ASP.Net interact when it comes to security. I have planned blog entries on this topic (rather, I need to finish up the series that I started a couple months ago...)

Once again, thanks for the encouragement.

//David