Niraj Bhatt – Architect's Blog

Ruminations on .NET, Architecture & Design

Tag Archives: Security

Cross Site Scripting (XSS) vs. Cross Site Request Forgery (CSRF)

This post not only highlights the difference between above but also gives bare bones steps (using ASP.NET Web Forms ) to reproduce them. Though there are more convoluted samples out there, having bare bones steps can help in better understanding of these terms.  Both XSS and CSRF are type of Web attacks. Wiki captures the essence of difference between them – Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF exploits the trust that a site has in a user’s browser. Let’s dig into them:

Cross Site Scripting

Description: Cross Site Scripting a relatively older attack talks about injecting malicious scripts in web pages which then would served to other users over a period of time. The malicious scripts in turn gains access to page content and start misusing it. A simple example could be someone entering a malicious JavaScript function in comments section of a webpage. When other users try to fetch that page they would also fetch malicious JavaScript and that can be devastating.

Solution: ASP.NET Web Forms can counter attack this by checking incoming requests for malicious scripts. ValidateRequest an attribute of Page Directive helps in preventing any incoming malicious scripts. Although ValidateRequest does a good job many don’t consider it foolproof. And a common recommendation is to use Server.HtmlEncode() for every output. Example:

Response.Write (“<script>alert(‘Niraj’)</script>”);
Response.Write(Server.HtmlEncode(“<script>alert(‘Niraj’)</script>”)); // Or HttpUtility.HtmlEncode

Simple Steps To Reproduce: Create a ASP.NET Page with TextBox, Submit Button & Label. Go to Button’s click event in code behind file and assign the content of textbox to label (without HtmlEncode). Run the application and and type script tag with alert message in textbox. Click on Submit button. You, on receiving response, would see that label is blank while an alert pops up on your screen. Go to CodeBehind file and wrap textbox’s text within HtmlEncode. Run the application again and output would be as per your expectations.

Cross Site Request Forgery

Description: Cross Site Request Forgery (also called One-Click) attack is lesser known though much easier to implant. Normally, a HTTP request is enough to get website into doing something. But most often that Website won’t allow your request to get through due to lack credentials. So how can a hacker lull you into providing your credentials? Ubiquitous way – a hacker can send you mail telling you won a grand prize and to claim it click on a link in his mail. You click and in case you are having persistent (though not necessary) authentication cookie (.ASPXAUTH) from site that hacker wants to manipulate, hacker would latch on it, use your credentials and send a HTTP request to that site. Remember the way browsers work is whenever you send a request for a specific domain also the cookies associated to that domain are also send across.

Solution: A preferred approach to counter attack this is bundle some user specific secret into the request which hacker won’t have access to. This secret is added while the page is created on server & is cross verified on every postback. ASP.NET Web Forms does it with help of ViewStateUserKey property while ASP.NET MVC leverages Html.AntiForgeryToken() method and ValidateAntiForgeryToken attribute.

Simple Steps to Reproduce: Create a web site with couple of pages. Go to web.config, set the authentication mode to Forms & specify the loginUrl as one of the pages. Go to that login page & place a button ‘Login’. Go to code behind file & in click event of ‘Login’ button add a single line –

FormsAuthentication.RedirectFromLoginPage(“YourName”, true);.

This will add a persistent cookie & redirect the user to requested page. In second page go to .aspx @Page directive and ensure it has – EnableViewStateMac=”true” attribute. That’s it, browse this page. You will get login page due to forms authentication. Click on Login Button to login. You will come to your requested page. Click on View -> Source of this page & copy the entire source (CTRL + C). Create a directory on your machine and create a text file in it and paste source in that. Rename the text file to dummy.aspx. Configure a virtual directory for dummy.aspx using Inetmgr. Edit dummy.aspx and add couple of lines after closing </form> tag. (N.B. copying an existing page is not required but that’s a common scenario – browse to similar page and get redirected even before you know what’s happening)

<script> document.form1.submit(); </script> (N.B. form1 is the default name of form generated by ASP.NET.)

Last step is to change ‘action’ attribute in form tag of dummy.aspx to point to the page where request should be posted.

<form method=”post” … action=”http://localhost/SomeVirtualDirectory/YourSecondPage.aspx”&gt;

That’s it. Open your inetmgr and try browsing dummy.aspx. Things should work fine and you would be redirected to your second page. You won’t be redirected to login page as you already have a persistent authentication cookie created. This is how attack is launched. Instead of going to inetmgr, you will open the link by clicking on Prize URL sent by hacker and the page would be hosted on hacker’s machine instead of yours.

To counter attack this go to YourSecondPage.aspx and add below method:

protected override void OnInit(EventArgs e)
//Add a user specific key to viewstate which will be verified later by ASP.NET
ViewStateUserKey = Session.SessionID;

If you try to browse now from inetmgr you would get an error stating – “Validation of viewstate MAC failed”. Prevention in place (N.B. you might get the same error while deploying your application on Web Farm, a solution for such a scenario can be found here).

There is also a general recommendation to allow interactions with your site via HTTPS only inorder to to prevent attacks like Session Hijacking, etc. Not doing so would give hackers easy access to session cookie – “ASP.NET_SessionID”. Finally parameterized queries are recommended to prohibit SQL injection attacks, server side validations should always be done, and custom cookies must set HttpOnly property to true.

For a more rigorous drill I recommend using Acunetix or WebInspect.

Any other techniques you always use? Hope above helps to some extent 🙂 .

Food For Thought – Do you accept password as clear text?

There are some subtle bugs we developers invite due to our backgrounds. I recently saw a configuration screen in an application (normally used by only admin) asking for connection string:

Preferred approach would have been:

Of course, connection timeout is missing in both 🙂 .

Speaking at MCT Summit 2009

I would be taking a session on – “Building Secure Web Services using WCF” at this MCT Summit. You can find the details about summit here. A brief introduction to my session is also there in the speakers list. To get there just search for my name 🙂 . In couple of days I will post the link to download demos I am going to demonstrate. Hope to see you there.