views:

844

answers:

3

I've written an application that handles most exceptions gracefully, with the page's design intact and a pretty error message. My application catches them all in the Page_Error event and there adds the exception to HttpContext.Curent.Context.Items and then does a Server.Transfer to an Error.aspx page. I find this to be the only viable solution in ASP.NET as there seems to be no other way to do it in a centralized and generic manner.

I also handle the Application_Error and there I do some inspection on the exception that occurred to find out if I can handle it gracefully or not. Exceptions I've found I can handle gracefully are such that are thrown after someone hacking the URI to contain characters the .NET framework considers dangerous or basically just illegal at the file system level.

Such URIs can look like e.g.:

  • http://exmample.com/"illegal"
  • http://example.com/illegal"/
  • http://example.com/illegal /

(notice the space before the slash at the end of the last URI).

I'd like these URIs to respond with a "404 Not Found" and a friendly message as well as not causing any error report to be sent to avoid DDOS attack vectors and such. I have, however, not found an elegant way to catch these types of errors. What I do now is inspect the exception.TargetSite.Name property, and if it's equal to CheckInvalidPathChars, ValidatePath or CheckSuspiciousPhysicalPath, I consider it a "path validation exception" and respond with a 404.

This seems like a hack, though. First, the list of method names is probably not complete in any way and second, there's the possibility that these method names gets replaced or renamed down the line which will cause my code to break.

Does anyone have an idea how I can handle this less hard-coded and much more future-proof way?

PS: I'm using System.Web.Routing in my application to have clean and sensible URIs, if that is of any importance to any given solution.

+3  A: 

It may be that System.Web.Routing supports some sort of url filtering, but it is quite easy to implement your own.

Look at the System.Web.IHttpModule interface and read about implementing custom HTTP Modules. Http modules enter that Asp.Net pipeline and run before your page is run. You can use it to perform logging of requests, to modify requests and in your case to filter requests. The Asp.Net routing module is also implemented as a custom HTTP Module.

What you can do is to implement a Http Module that looks at the requested url and check if it is valid. If the url is invalid you can do whatever you need, for example redirect it to your 404 - not found page or you can just stop the request.

Rune Grimstad
I agree that this would be the best solution. If you handle the issue before it actually occurs, then you will be saving server resources. I also want to add that in your module, you should probably attach the check url function to the HttpApplication.BeginRequest event.
regex
Thanks for the suggestion. I've now implemented it a bit differently, but will probably extract most of that logic into an HttpModule when time permits.
asbjornu
A: 

I don't think using System.Web.IHttpModule is the correct answer for IIS7+. I am trying to implement IHttpModule to validate the path but the exception has been thrown before the HttpModule is executed.

This is my exception stack:

   [ArgumentException: Illegal characters in path.]
   System.IO.Path.CheckInvalidPathChars(String path) +7493413
   System.IO.Path.Combine(String path1, String path2) +40
   System.Web.Configuration.UserMapPath.GetPhysicalPathForPath(String path, VirtualDirectoryMapping mapping) +114
   System.Web.Configuration.UserMapPath.GetPathConfigFilename(String siteID, VirtualPath path, String& directory, String& baseName) +72
   System.Web.Configuration.UserMapPath.MapPath(String siteID, VirtualPath path) +30
   System.Web.Configuration.UserMapPath.MapPath(String siteID, String path) +31
   System.Web.Hosting.HostingEnvironment.MapPathActual(VirtualPath virtualPath, Boolean permitNull) +297
   System.Web.Hosting.HostingEnvironment.MapPathInternal(VirtualPath virtualPath, Boolean permitNull) +51
   System.Web.CachedPathData.GetConfigPathData(String configPath) +341
   System.Web.CachedPathData.GetVirtualPathData(VirtualPath virtualPath, Boolean permitPathsOutsideApp) +110
   System.Web.HttpContext.GetFilePathData() +36
   System.Web.HttpContext.GetConfigurationPathData() +26
   System.Web.Configuration.RuntimeConfig.GetConfig(HttpContext context) +43
   System.Web.Configuration.CustomErrorsSection.GetSettings(HttpContext context, Boolean canThrow) +41
   System.Web.HttpResponse.ReportRuntimeError(Exception e, Boolean canThrow, Boolean localExecute) +101
   System.Web.HttpRuntime.FinishRequest(HttpWorkerRequest wr, HttpContext context, Exception e) +383

and this is the link to Application Life Cycle for IIS 7.0 (http://msdn.microsoft.com/en-us/library/bb470252.aspx)

I am guessing that the exception caused by the "RESOLVE CACHE" step

ensecoz
A: 

Writing Custom HttpModule didn't work for me - I still got the "Illegal characters in path" error, but answer to this question solved the problem.

PanJanek