English | 中文 | Русский | Français
2,856 Posts served
8,606 Conversations started
Hacking Intel: XSS Security exploit with ASP.Net using .RewritePath and Request.RawUrl bypassing ASP.Net native script protection (.Net 1.1 and 2.0)
What is XSS: http://en.wikipedia.org/wiki/Cross-site_scripting XSS also called Cross-Site Scripting is a web based security vulnerability by which a person injects HTML or Client side script code into a web page without the knowledge of the originator of the web page.
Web 2.0 enhanced GUI experiences and RTF editors go hand in hand and the increased support and ability to POST HTML content (and to protect against malign intent) means that XSS becomes a more serious issue on a daily basis. Practically weekly a new hack or workaround enabling a user to inject malign content gets found.
Any web page that can take as input QueryString or POST input like <SCRIPT>alert("hello from script")</SCRIPT> and echo's it back can practically be considered a XSS exploitable site. Other simple variations on this theme are described but another simple one that I will consider here is </SCRIPT><SCRIPT>alert("hello from script")</SCRIPT>
Securing ASP.Net: Typically ASP.Net web page developers rely on one or two mechanisms to prevent XSS issues. The fist layer of protection is found already set on in most machine.config files.
<configuration>
<system.web>
<pages validateRequest="true" />
This is a first level of protection and can be explicitly set in web.config files or down to the @Page level for making allowances of HTML RTF editor posted content. With validateRequest set to "false" we now start to enter the realm of the XSS exploitable web site. From this point on it is would be considered on part of the developer to scan and remove CSS includes, JavaScript:, <script> tags, and more advanced versions like style style="any: expression(window.location=myevilsite.com)" from all submitted content. The developer must also check the content for same origins policy for all allowable HTML to ensure that malign viral images, embed objects etc are stripped out. Quite a tall order for most developers.
For the life of me I have not found a good ASP.Net content scrubber DLL that maintains a same origins policy but my concern extends beyond just page content cleanup.
Rewrite Path XSS Exploit: (perhaps not all that new good to be aware of) This is not a common problem for most web applications but can impact those applications that make use of virtualized URL's to help organize content. I need to throw a little background at you before I lay out the new XSS exploit.
Take for example a blog that wants to organize content by year, month. The old format for posts might take on ShowBlogPostings.aspx?year=NNNN&month=NN which is not very friendly. Using virtualized URL's you can easily create a group view using something like http://../myblog/2007/11/index.html for the base URL which could easily be re-written using an ASP.Net IHttpModule with .RewritePath(SOMEURLHERE) by parameterized calls against the virtualized URL into the original format. So with /myblog/2007/11/index.html we can take out the year and month via some easy expression pattern like /myblog/(.*?)/(.*?)/index.html and call .RewritePath(ShowBlogPostings.aspx?year=$1&month=$2) thus insulating the user and providing better organization of data.
So lets take that URL and malign it to /myblog/(.*?)/(.*?)/index.html?a= </SCRIPT><SCRIPT>alert("XSS Exploited")</SCRIPT> and using the .RewritePath(ShowBlogPostings.aspx?year=$1&month=$2) I echo the Request.RawUrl to the web page and BOOM!
Doing some more isolation work on this XSS exploit to determine why it was getting by I've found that if my re-write path is plain or without QueryString parameters to the page i.e. "ShowBlogPostings.aspx" that ASP.Net responds with a proper error message (A potentially dangerous Request.QueryString value was detected from the client (a="</SCRIPT><SCRIPT>alert("XSS E...") like you would expect. Once the .RewritePath contains QueryString parameters i.e. (ShowBlogPostings.aspx?year=$1&month=$2) then it slips right by. and there will be no error message or issue with the ASP.Net worker engine. Any page that echoes back RawUrl will be in trouble. (ASP.Net FORM ACTION takes on the rewritten URL which is a site virtualization issue but I would skip that here as being out of scope)
Part of the problem was our initial expression in that it only looked for a partial match of content instead of being more explicit and passing on extra parameters. Best code track would be a first pattern of /myblog/(.*?)/(.*?)/index.html?(.*) and only then handling the original pattern of /myblog/(.*?)/(.*?)/index.html. Basically by not passing on all the data the XSS vulnerability was found. With the original pattern the RewritePath call is made .RewritePath("ShowBlogPostings.aspx?year=$1&month=$2"); which tosses out additional parameter data in $3. The context of the original Request.RawUrl is maintained and thus bypass the page validateRequest mechanism without error or incident.
My last thought on this is why one might use RawUrl let alone echo it back into a web page? Request.RawUrl can be tossed into a HIDDEN FORM field for navigation or into a login or logout script links to provide a quick way to get back and forth between web pages. There are as many reasons to use Request.RawUrl as there are developers on the planet, so who's to say?
Developer Response: Don't trust end user data submissions and URL or HTML encode all Request variables (QueryString, Post, Etc..) It's hard to believe that problems like this have been around since 2003 or earlier and they keep cropping back up.
http://weblogs.asp.net/gad/archive/2003/11/12/37219.aspx
http://weblogs.asp.net/rhurlbut/archive/2004/02/04/67684.aspx
Rebuild reflected URL's manually (use the .Net call of System.Uri u = new Uri(someurl); to break the URL apart) on the fly, don't rely upon Microsoft to provide safe data handling either and be paranoid, mistrustful.
Use the Microsoft Anti-Cross Site Scripting Library http://msdn2.microsoft.com/en-us/security/aa973814.aspx for everything.
Use White Lists (allowed) over Black (disallowed) Lists http://www.feedparser.org/docs/html-sanitization.html and know what you will consider safe for your site (in this day and age and localized application sets that might be a tough call to do.) Consider all Request fields that will not contain HTML to encoded. For HTML submittals consider a granularity down to acceptable attribute's and tags to accept and toss the rest, better safe than sorry!
Microsoft's Response: No idea yet. Perhaps this has already been discovered. Will post more on this as I become aware of it.
Stefan Schackow - This functionality would be more like a DCR for a future ASP.NET release rather than a security bug with a clear fix. Although the query string portion of the raw Url could be included in request validation pretty easily, we don’t perform the same validations on the path segments of a Url. With rewritten Urls the entirety of the Url becomes interesting to an attacker, not just the query string portion.We do have future plans to expand the scope of the request validation feature, and that’s where I think this kind of work would make sense. On my end I’ll enter a DCR about this so that we don’t lose track.Conclusion: Though I have not delved into Microsoft's code via Lutz Reflector http://www.aisto.com/roeder/dotnet/ I would think this exploit a principal violation that Microsoft should protect against with validateRequest and that they should fix it. If anyone is aware of a patch or better approach please drop a message here. If you know of a manual way to trigger the validateRequest that would be nice to know as well.

teamelite