Use any characters you want in your URLs with ASP.NET 4 and IIS 7!

After spending entirely too much time researching this issue today here is how you can use any characters you want for URLs in ASP.NET 4 and IIS 7. A bit of background: I am writing a web application that has a custom HttpModule and HttpHandler that should handle all requests and not limit the syntax of those requests at all. I could not find the information on how to do this in one place anywhere, and there are a reasonable amount of misleading, unanswered and naive responses on various forums that will likely lead you astray if you have an advanced configuration like mine. There are also a lot of completely out of date posts centered on .NET 1.1 and .NET 2.0.

The first thing I was trying to do was make a POST-ed form value containing a forward slash into something that could be used as a component in a RESTful URL. I tried to accomplish that by implementing a handler for AuthenticateRequest in my HttpModule (you can’t do it in BeginRequest unless you want to read the form data manually because Request.Form is not intialized yet) that would encode the value and call TransferRequest. First that made this happen:

A potentially dangerous Request.Path value was detected from the client (%).

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.HttpException: A potentially dangerous Request.Path value was detected from the client (%).

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below


Stack Trace:

[HttpException (0x80004005): A potentially dangerous Request.Path value was detected from the client (%).]
   System.Web.HttpRequest.ValidateInputIfRequiredByConfig() +8815985
   System.Web.PipelineStepManager.ValidateHelper(HttpContext context) +59

Okay. ASP.NET, for security reasons, normally protects your web applications from potentially harmful content being sent to them, which is probably a good thing. But what if we want or need potentially harmful content? Should we be limited? I hoped the answer was “no”, but the almost complete lack of information on the subject sure wasn’t making it seem that way. After some not too helpful reading and some digging with Reflector, I came up with this:

<system.web>
<httpRuntime requestPathInvalidCharacters="" />
<pages validateRequest="false" />
</system.web>

Now no characters are invalid and requests shouldn’t even BE validated right? WRONG. While this did clear up the first exception, I faced a new one. And, while I was not sure if the validateRequest setting would even apply to my case since it is on the pages element, I assure you that for some reason that setting is an integral part of the above and following changes to work properly together. Here was my second roadblock:

Error Summary

HTTP Error 404.11 – Not Found

The request filtering module is configured to deny a request that contains a double escape sequence.

Detailed Error Information
Module RequestFilteringModule
Notification BeginRequest
Handler Clear
Error Code 0×00000000
Requested URL http://localhost:80/Clear/search/x%2Fy
Physical Path D:\Development\Clear\Clear\search\x%2Fy
Logon Method Not yet determined
Logon User Not yet determined
Most likely causes:
  • The request contained a double escape sequence and request filtering is configured on the Web server to deny double escape sequences.
Things you can try:
  • Verify the configuration/system.webServer/security/requestFiltering@allowDoubleEscaping setting in the applicationhost.config or web.confg file.
Links and More Information

This is a security feature. Do not change this feature unless the scope of the change is fully understood. You should take a network trace before changing this value to confirm that the request is not malicious. If double escape sequences are allowed by the server, modify the configuration/system.webServer/security/requestFiltering@allowDoubleEscaping setting. This could be caused by a malformed URL sent to the server by a malicious user.View more information ยป

Great, now it didn’t even look like it was getting from IIS to ASP.NET! However, deciding I “fully understood” the change, this problem was much easier to find a solution to and get past. Once again, it was a simple matter of adding the right magic words to the Web.config:

<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>
</system.webServer>

Finally my Frankenstein was coming to life and I thought I was in the clear. But, then I realized that when other clients (not form POST-ers who would not realize my HttpModule was secretly processing their inputs) wanted to send me a URL with a forward slash in a path component they would have to double encode or use some other strange method to identify it as a different kind of forward slash then the normal path component delimiter.

So, I decided to add a feature to my framework that would allow a syntax to specify that “the rest” of a URL is a single component and to do that I wanted to use “/*”. Convinced I could use any character I wanted now, I went ahead and ran the debugger with my test path, and to my chagrin ran into this little beauty:

System.ArgumentException occurred
Message=Illegal characters in path.
Source=mscorlib
StackTrace:
at System.Security.Permissions.FileIOPermission.HasIllegalCharacters(String[] str)
InnerException:

mscorlib.dll!System.Security.Permissions.FileIOPermission.HasIllegalCharacters(string[] str) + 0x117 bytes
mscorlib.dll!System.Security.Permissions.FileIOPermission.AddPathList(System.Security.Permissions.FileIOPermissionAccess access, System.Security.AccessControl.AccessControlActions control, string[] pathListOrig, bool checkForDuplicates, bool needFullPath, bool copyPathList) + 0x4a bytes
mscorlib.dll!System.Security.Permissions.FileIOPermission.FileIOPermission(System.Security.Permissions.FileIOPermissionAccess access, string[] pathList, bool checkForDuplicates, bool needFullPath) + 0x2c bytes
mscorlib.dll!System.IO.Path.GetFullPath(string path) + 0x5c bytes
System.Web.dll!System.Web.Util.FileUtil.IsSuspiciousPhysicalPath(string physicalPath, out bool pathTooLong) + 0x42 bytes
System.Web.dll!System.Web.Util.FileUtil.IsSuspiciousPhysicalPath(string physicalPath) + 0x18 bytes
System.Web.dll!System.Web.Util.FileUtil.CheckSuspiciousPhysicalPath(string physicalPath) + 0x9 bytes
System.Web.dll!System.Web.CachedPathData.GetPhysicalPath(System.Web.VirtualPath virtualPath) + 0x77 bytes
System.Web.dll!System.Web.CachedPathData.GetConfigPathData(string configPath) + 0x190 bytes
System.Web.dll!System.Web.CachedPathData.GetVirtualPathData(System.Web.VirtualPath virtualPath, bool permitPathsOutsideApp) + 0x6f bytes
System.Web.dll!System.Web.HttpContext.GetFilePathData() + 0x25 bytes
System.Web.dll!System.Web.HttpContext.GetConfigurationPathData() + 0x1b bytes
System.Web.dll!System.Web.Configuration.RuntimeConfig.GetConfig(System.Web.HttpContext context) + 0x2c bytes
System.Web.dll!System.Web.HttpContext.SetImpersonationEnabled() + 0xd bytes
System.Web.dll!System.Web.HttpApplication.AssignContext(System.Web.HttpContext context) + 0x5c bytes
System.Web.dll!System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest wr, System.Web.HttpContext context) + 0x22f bytes
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr managedHttpContext, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) + 0x1fc bytes
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr managedHttpContext, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) + 0x29 bytes
[Appdomain Transition]

So, in a last desperate attempt to not have to give up, I circled back to a solution that had not worked for any of the other problems I ran into before and to my surprise, it all worked out. Unfortunately, it requires adding a registry value, apparently making your entire server less secure and not an option except for in the most “all access” hosting environments. Anyway, you need to set the following to get the last few “illegal” characters to be allowed:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\VerificationCompatibility = 1 (32-bit DWORD)

Before I get accused of hacking my way out of this, this is actually a recommended fix from Microsoft written when this feature was first added as a service pack for .NET 1.1 but it is apparently still in there and for guys like me who like to push the limits, I thank them for trusting us a tiny bit:

http://support.microsoft.com/default.aspx?scid=kb;EN-US;826437

I did find one posting that sort of talks about this problem (on Scott Hanselman’s blog) but it appears rather than finding a solution they opted to change their URLs to workaround the problem. Yes, maybe that was a better idea, but not nearly as FUN:

http://www.hanselman.com/blog/BUGCantUseAnAsteriskAsACharacterWhenRequestingAURLPageFromASPNET.aspx

Hopefully this will help someone get past the issue themselves without all the forumining and experiments, or at least convince them it’s a bad idea and give up on the special characters. ;)

This entry was posted in Development, Web and tagged , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

55 Comments

  1. Posted August 30, 2014 at 6:20 pm | Permalink

    I read a lot of interesting articles here. Probably you spend a lot
    of time writing, i know how to save you a lot of time, there is an online tool that creates high quality, google friendly posts in seconds, just type in google – laranitas free content source

  2. Posted August 30, 2014 at 9:20 pm | Permalink

    Excellent goods from you, man. I have understand your stuff previous to and you’re just extremely wonderful.
    I actually like what you’ve acquired here, certainly like what you’re
    stating and the way in which you say it. You make it entertaining and you still take care
    of to keep it smart. I cant wait to read much more from you.
    This is really a great website.

  3. Posted September 7, 2014 at 11:57 am | Permalink

    It’s an remarkable paragraph in support of all the web users;
    they will get advantage from it I am sure.

  4. Posted September 8, 2014 at 7:52 am | Permalink

    Hi there to every one, as I am genuinely keen of reading this blog’s
    post to be updated daily. It includes pleasant stuff.

  5. Posted September 9, 2014 at 6:28 pm | Permalink

    Of all the examining and competitiveness which goes on, on who has got the biggest penile.

    Nowadays, in line with the commonly accepted reports,
    Peyronie’s disorder has an effect on millions of adult men commonly starting in their 50′s.

    Not long ago, a penis pump called Bathmate has emerged.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>