Allow Double URL Encoded Request Paths To Be Valid - asp.net

I have a standard ASP.Net WebForms application running on IIS 7.0 with an Integrated Managed Pipeline. Many of the images on our site have spaces in their files names (e.g. './baseball drawing.gif'). When we place these images into our html pages we url encode the paths so that our html img tags look like this <img src='./baseball%20drawing.gif' />
Now, the problem comes in when certain search engines and webcrawlers try to index our site. When they scrape our pages they will html encode our already html-encoded paths getting image links like this './baseball%2520drawing.gif' where %25 is the url encoding for '%'. This causes two problems:
When users get results from these search engines they receive broken links.
When users attempt to navigate to these broken links it throws errors in our system.
As you can see this is a lose lose situation. Users get broken links, and we get noise in our error logs.
I've been trying to figure out how to correct this problem with no luck. Here is what I've tried:
Set <requestFiltering allowDoubleEscaping='true'> in web.config to prevent the "404.11 URL Double Escaped error". This fixed the first error but caused a new one, "a potentially dangerous Request.Path was found".
Removed the '%' from the <httpRuntime requestPathInvalidChars> to prevent the "potentially dangerous Request.Path" error. This fixed the second error but now we have a third one, "Resource can't be found".
I placed a break in my code to watch Request.Path. It looks like it is right with a value of 'Ball Image.gif' instead of 'Ball%2520Image.gif'. With this being the case I'm not sure why it isn't working.
I feel like I have a super hack where I am having to disable everything without really understanding why nothing is working. So I guess my question is three fold
Why did solution attempt 1 not take care of the problem?
Why did solution 2 not take care of the problem?
Why does my Request.Path look right in step 3 but it still doesn't work?
Any help anyone can provide would be greatly appreciated.

OK, after much searching of the internets and plenty of experimentation I think I finally understand what is going on. My main problem was a case of extreme confirmation bias. Everything I read said what I wanted to hear rather than what it actually said. I am going to summarize greatly the key points I needed to understand in order to answer my question.
First, I needed to understand that IIS and ASP.Net are two different applications. What IIS does in a nutshell is receive a request, route that request to an application that handles it, gets the output from the handling application, and then sends the output from the application back to the requester. What ASP.Net does is receive the request from IIS, handle it, and then pass the response back to IIS. This is a huge over-generalization of the whole process but for my purposes here it is good enough.1
Incoming ASP.Net requests have to pass through two gatekeepers. The IIS7 RequestFiltering module(configured in system.webserver/requestFiltering2), and then the ASP.Net HttpRuntime request filters(configured in system.web/httpRuntime3).
The IIS RequestFiltering module is the only one that normalizes incoming requests and it only applies normalization ONE time. Again I repeat it only applies it ONE time. Even if <requestFiltering allowDoubleEscaping="true" /> it will still only apply normalization once. So that means '%2520' will be normalized to '%20'. At this point if allowDoubleEscaping is false IIS will not let the request through since '%20' could still be normalized. If, however, allowDoubleEscaping is set to true then IIS7 will pass off the request '%20' to the next gatekeeper, ASP.Net. This was the cause of the first error.
The Asp.net filter is where the requestPathInvalidCharacters are checked. So now our '%20' is invalid because by default '%' is a part of requestPathInvalidCharacters. If we remove the '%' from that list we will make it through the second gatekeeper and ASP.Net will try to handle our request. This was the cause of the second error.
Now ASP.net will try to convert our virtual path into a physical one on the server. Unfortunately, we still have a '%20' in our path instead of the ' ' we want so ASP.Net isn't able to find the resource we want and throws a "resource can't be found error". The reason the path looked right to me when I broke in my code is because I placed a watch on the Request.Url property. This property tries to be helpful by applying its own normalization in its ToString() method thus making our %20 look like the ' ' we want even though it isn't. This was the cause of the final error.
To make this work we could write our own custom module that receives the request after the first two gatekeepers and fully normalizes it before handing it off to ASP.Net. Doing this though would allow any character to come through as long as it was URL encoded. For example, we normally don't want to allow a '<' or a '>' in our paths since these can be used to insert tags into our code. As things work right now the < and > will not get past the ASP.Net filter since they are part of the requestPathInvalidCharacters. However, encoded as a %253C and a %253E they can if we open the first two gates and then normalize the request in our own custom module before handing it off to ASP.Net.
In conclusion, allowing %2520 to be fully normalized can't be done without creating a large security hole. If it were possible to tell the RequestFiltering module to fully normalize every request it receives before testing that request against the first two gatekeepers then it would be much safer but right now that functionality isn't available.
If I got anything wrong let me know and I hope this helps somebody.

If you want to allow double-escaping, you can follow the instructions at
http://www.iis.net/ConfigReference/system.webServer/security/requestFiltering
It worked for me on IIS 7.0 with no other configuration required. Double-escaping has no impact for the code of the web site I implemented it on; I don't know what potential security implications there could be for other sites.

Related

Recognize the pattern: what system is malforming my query string parameters?

We have a fairly complicated ASP.NET MVC project with cross domain login widgets and a lot of semi-legacy code.
There is a system where we login people through an iframe. The url for the iframe we send through a string attached to the MVC Model.
Problem is; on really rare occassions we see malformed query string parameters coming through. It's always the same malformation though. I want to fix the issue, but I can't figure out why this happens.
I'm expecting some Adblocker-type or privacy settings, or maybe some Regional settings, but I have no clue where to start.
I am hoping someone will recognize the pattern and say; that's a localization pattern when your Windows is set on Turkey or whatever, you should check your encoding etc etc.
Anyway here's the example:
Expected:
auth-dialog-window?openerOrigin=https%3a%2f%2f.poules.com&color=C3042E&openerType=iframe
Coming through:
auth-dialog-window?color=P304212R&openerType=vsenzr&openerOrigin=uggcf%3N%2S%2Scbhyrf.pbz
Apparently the order of the query string also changes. Here more closely per parameter:
iframe
vsenzr
https:// poules.com (spaces are for aligning)
uggcf%3N%2S%2Scbhyrf.pbz
C3042E
P304212R
Does anyone recognize the pattern and can give me a hint where I should be looking?
I know for sure the last time it happened with IE 9.0, but can't reproduce it.
ROT-13.
A system somewhere is "trying to crypt" in a very simple way...
Check "pairs" of letters in both values:
abcdefghijklmnopqrstuvwxyzabcdefghijklm
nopqrstuvwxyzabcdefghijklmnopqrstuvwxyz

Determine if requester is an Ajax call and/or is expecting JSON (or another content type)

I have solved a problem with a solution I found here on SO, but I am curious about if another idea I had is as bad as I think it might be.
I am debugging a custom security Attribute we have on/in several of our controllers. The Attribute currently redirects unauthorized users using a RedirectResult. This works fine except when calling the methods with Ajax. In those cases, the error returned to our JS consists of a text string of all the HTML of our error page (the one we redirect to) as well as the HTTP code and text 200/OK. I have solved this issue using the "IsAjaxRequest" method described in the answer to this question. Now I am perfectly able to respond differently to Ajax calls.
Out of curiosity, however, I would like to know what pitfalls might exist if I were to instead have solved the issue by doing the following. To me it seems like a bad idea, but I can't quite figure out why...
The ActionExecutingContext ("filterContext") has an HttpContext, which has a Request, which in turn has an AcceptTypes string collection. I notice that on my Ajax calls, which expect JSON, the value of filterContext.HttpContext.Request.AcceptTypes[0] is "application/json." I am wondering what might go wrong if I were to check this string against one or more expected content types and respond to them accordingly. Would this work, or is it asking for disaster?
I would say it works perfect, and I have been using that for years.
The whole point use request headers is to be able to tell the server what the client accept and expect.
I suggest you read more here about Web API and how it uses exactly that technique.

Handling HttpRequestValidationException ASP.net 4.0

This is my first time doing a project in ASP so this is my first time running into the dreaded A potentially dangerous Request.Form value was detected from the client... error.
I've looked around the web and stackoverflow, and can't seem to find a "best practice" way to deal with this. I don't exactly want to turn off all validations, because that would mean that in every single text box where the user can input data, I need to have to encode/decode the text myself right? Which leads me to think that this is a very easy way to leave security holes in your site.
Another seemingly common fix is to have the validation break gracefully and lead to a nicer looking error page for the user, which isn't a bad fix, but it can't be the best right?
I've noticed on most sites, if you enter the HTML encoding for a apostrophe for example, it automatically turns into a apostrophe character. As I type this now, if I try to type in &#39 ; (take away the space between 9 and ; and this is the HTML encoding for apostrophe), it automatically gets converted into a '. There has to be a way in ASP.net 4.0 to do the same thing?
Btw, I'm using c# as my backend server side code.

ASP.NET: Looking for solution to solve XSS

We got a long-running website where XSS lurks. The problem comes from that some developers directly - without using HtmlEncode/Decode() - retrieve Request["sth"] to do the process, putting on the web.
I wonder if there is any mechanism like HTTPModule to help us HtmlEncode() all the items in a Http request to avoid XSS to some extent.
Appreciate for any suggestion.
Rgds,
Ricky
The problem is not retrieving Request data without HTML-encoding. In fact that's perfectly correct. You should not encode any text until the final output stage when you spit it into an HTML page.
Trying to blanket-encode incoming parameters, whether that's HTML-encoding or SQL-encoding, is totally the wrong thing. It may hide XSS holes in your app but it does not fix them. You will still have a hole if you output content that hasn't come from parameters, or has been processed since then. Meanwhile the automatic encoding will fill your database with multiply-escaped &amp;amp;amp;amp;amp;amp; crud.
You need to fix the output stage, that's where the problem lies.
Like bobince said, this is an output problem, not an input problem. If you can isolate where this data is being output on the page, you could create a Filter and add it to the Response object. This filter would isolate the areas that are common output and then HtmlEncode them.

Asp.Net Validaterequest False

I'm creating an Asp.Net program UI where users can browse and change information in a database. For this reason, they need to be able to use all forms of chars, but I still need to keep the program HTML and SQL itself secure. For that reason, I'm using a self-built method that replaces dangerous chars such as '<' etc with their html-codes while they're being handled outside of a textbox (issued on page-load so they have no functionality in there).
Now my dilemma: To be able to do this, I have to disable the Validaterequest parameter as per the topic, the program will issue a complaint. What are the possible consequences of setting it to False?
The SQL query is parametirized already, and I filter out the following marks only:
& # < > " ’ % # =
Question: am I leaving the program open for threats even if I handle the chars above? Basically this is an intranet application where only a few people will be able to access the program. Nevertheless, the information it accesses is fairly important so even unintentional mishaps should be prevented. I literally have no idea what the Validaterequest thing even does.
Edit: Alright, thx for the answers. I'll just go with this then as initially planned.
The main things Validate Request is looking for are < and > characters, to stop you opening your site up to malicious users posting script and or HTML to your site.
If you're happy with the code you've got stripping out HTML mark-up, or you are not displaying the saved data back to the website without processing, then you should be ok.
Basically validating user input by replacing special characters usually cause more trouble and doesn't really solve the problem. It all depends what the user will input, sometimes they need the special characters like
& # < > " ’ % # =
think about savvy users could still use xp_ command or even use CONVERT() function to do a ASCII/binary automated attack. As long as you parametrized all input, it should be ok.
i think that the problem is not only about SQL injection attacks, but about Cross Site Scripting and JS execution attacks.
To prevent this you cannot rely on parametrized queries alone, you should do a "sanitization" of the html the user sends! maybe a tool like html tidy could help.

Resources