The Experience ASP.NET MVC 3 Beta series
Part 1 In the coming ASP.NET MVC 3.0 a lot of new good things will be added or enhanced. In this article, we are going to focus upon the new view engine Razor to see how it will simplify the view design.
Part 2 In addition to the introduction of a new view engine Razor, ASP.NET MVC 3 Beta has also introduced numerous new HtmlHelpers, such as Chart, Crypto, WebGrid, WebImage, WebMail, etc. This article aims to introduce the two commonly-used new helper controls – WebGrid and Chart using relevant examples.
Part 3 In this installment, I'll first tell you a short story about unobtrusive JavaScript. Then, we'll delve into the unobtrusive client-side validation support. Finally, we will research into a more interesting story - the unobtrusive jQuery-Based Ajax support.
Part 4 In this article, we are going to continue to explore the other three important helpers - WebImage, WebMail, and Crypto.
Part 5 Starting from this article, let's explore some more advanced concepts and related utilizations associated with flexible Dependency Injection support introduced in ASP.NET MVC 3 Beta.
Part 6 In the last article, we've mainly discussed the new-styled DI support in ASP.NET MVC 3 Beta/RC in relation to the two new services - IControllerActivator and IViewPageActivator. Obviously, both of them are connected with controllers and views. In this article, however, we will shift our attention to the Model (generally called viewmodal in many blogs) related DI manipulations.
Part 7 Since ASP.NET MVC 1, CSRF (Cross Site Request Forgery) has been considered by introducing a set of anti-forgery helpers. In this article, we are to detail into CSRF related concepts and ASP.NET MVC's helper functions again CSRF.
Part 8 In this series of articles, we are going to explore as many as possible aspects of cache programming in the latest ASP.NET MVC 3 RC2 framework. And also, all the related samples have been tested against the latest ASP.NET MVC 3 RC 2.
Part 9 In the first part of this series, we've mainly explored Output Cache related issues. In this second part, however, we are going to delve into the general Data Cache topic.
Introduction
Network security becomes one of the first issues to consider in modern Web development. In general, the most common types of Web attacks from the point view of software include Cross-site Scripting (XSS), SQL Injection, Session hijacking, Cross-site Request Forgery (CSRF), and Hidden field tampering. Compared with the other web attacks, CSRF attacks are probably the least well known, so that they are easier to exploit, with extreme and increasing danger.
The good news is, since ASP.NET MVC 1, CSRF has been considered by introducing a set of anti-forgery helpers. In this article, we are to detail into CSRF related concepts and ASP.NET MVC's helper functions again CSRF.
NOTEThe test environments we'll utilize in the sample application are:
1. Windows XP Professional (SP3);
2. .NET 4.0;
3. Visual Studio 2010;
4. ASP.NET MVC 3 RC (http://www.microsoft.com/downloads/en/details.aspx?FamilyID=a920ccee-1397-4feb-824a-2dfefee47d54);
What’s Cross-Site Request Forgery (CSRF)
In the industry, alongside XSS (Cross Site Scripting) and SQL Injection, Cross-site Request Forgery (CSRF) attacks represent the three most common and dangerous vulnerabilities to common web applications today. CSRF attacks are probably the least well known yet relatively easy to exploit.
According to wikipedia's definition, cross-site request forgery, "CSRF" in short, is a confused deputy attack against a Web browser. The attack works by including a link or script in a page that accesses a site to which the user is known (or is supposed) to have been authenticated. As long as the attacker uses some tricks, such as by e-mail or chat software to send the link, the attacker will be able to force a Web application user to perform the selection operation of the attacker.
The following characteristics are common to CSRF:
- Involve sites that rely on a user's identity
- Exploit the site's trust in that identity
- Trick the user's browser into sending HTTP requests to a target site
- Involve HTTP requests that have side effects
By the way, CSRF is also called "one-click attack" by Dino Esposito in his article at MSDN, where he brought us a vivid picture to illustrate what CSRF was. For brevity, we are to omit the detailed description.
Ways to stop CSRF
On the whole, there are three widely-used techniques for defending against CSRF attacks, as enumerated below.
- Use a user-specific token
- Validate the HTTP Referer header
- Set a custom header via XMLHttpRequest
This first way may be the most popular approach to defense CSRF. In detail, put a user-specific token as a hidden field in legitimate forms (often use some random value, such as a GUID, stored in the visitor's Session collection or into a Cookie), and validate that the received token is correctly bound to the user's session.
This second is the simplest way to defense CSRF. In detail, make the server side accept requests only from trusted sources. There is an obvious deficiency associated with this technique – the server has to deal with requests lacking a Referer header entirely. Thus, sites can either process these requests or block them. If a site processes requests that lack a Referer header, the solution may be dangerous because the Referer header can be suppressed by an attacker. On the other hand, if the site refuses to process these requests, an appreciable part of users will be excluded.
The last action against CSRF is related to XMLHttpRequest. Ajax's popularity has increased recently with more sites implementing AJAX interfaces. Sites can defend against CSRF by setting a custom header via XMLHttpRequest and validating that the header is present before processing state-modifying requests. Although effective, this defense requires sites to make all state-modifying requests via XMLHttpRequest, a requirement that prevents many natural site designs. Although this article is not going to explore the AJAX related CSRF issue, DiXin did give you a good solution in this aspect, to be mention later on.
NOTEAccording to the HTTP RFC #2616 Section 9.1.1 Safe Methods, GET should not have the significance of taking an action. They shouldn't be allowing GET requests to take actions.
Cross-site Request Forgery Attack Samples
In Phil Haack’s blog, he presented us a detailed yet simple banking sample to illustrate how the hacker performed the CSRF attack upon a common banking account if the web system didn't take anti-forgery actions. For brevity, I'm not going to give such similar samples but leave space to the real topic – ASP.NET MVC's anti-forgery solution.
ASP.NET MVC’s Solution to Prevent CSRF
To defense the CSRF attach, ASP.NET MVC has introduced a group of anti-forgery methods since version 1.0. In detail, they are:
AntiForgeryToken: a public method of the HtmlHelper class.
- AntiForgeryData: an internal class containing the anti-forgery related data.
- AntiForgeryDataSerializer: an internal tool class, which is used to encode/decode the AntiForgeryData structure mainly through the Base64 coding and decoding algorithms.
- The
ValidateAntiForgeryToken attribute: when some special actions in the controller are decorated with this attribute an anti-forgery related validation will be performed.
In fact, ASP.NET MVC right takes the first technique described above– create a user-specific token, to try to avoid CSRF.
Easily seen, the key lies in the HTML Helper method AntiForgeryToken. When we call @Html.AntiForgeryToken() (in this case we use the new Razor syntax) in a form on our view page we will obtain a hidden input and a Cookie with a random string assigned. The Html.AntiForgeryToken method will create a cookie on the client-side machine and adds a hidden field (to be detailed later).
And then, on our target action method in the controller we need to add the [ValidateAntiForgeryToken] attribute, which will handle the verification that the correct token was supplied.
In detail, to protect a particular HTML form, we just need to include the method invocation to Html.AntiForgeryToken() inside the form, like this:
In this way, Html.AntiForgeryToken() will give the visitor a cookie called __RequestVerificationToken_Lw__, with the same value as the random hidden value implies above.
To gain more details, let's use the above anti-forgery helpers to build up a concrete sample application.
Put the AntiForgery Helpers into action
1. Create Model
Now, let's first define a simple model named CustomerViewModel, as follows.
2. Create anti-forgery required action
Now, let's create a pair of actions both named Login. Obviously, the first one is used to trigger the related view page Login.cshtml; the second one will be used to deal with the POST request sent out from the view page.
The first point to notice is in the second method we've decorated it with the [HttpPost] attribute, which will cut off all possible requests made through a plain GET. In fact, as stressed previously, this is a MUST HAVE to mitigate CSRF attacks.
Next, to validate an incoming form post, we have to add the [ValidateAntiForgeryToken] filter to the second action method. If the validation passes (and no CSRF attack takes place), we navigate the use to the Index view page related to the Home controller – just for test's aim; or else, an error info will be returned.
In other words, ValidateAntiForgeryToken instructs the invoker of the ASP.NET MVC method to look for some special content in the request body before executing the code.
More specifically, the ValidateAntiForgeryToken attribute contains code that kicks in during the authorization phase of an action method request, ensuring the posted request contains a cookie and a form field with a common fixed name. If any of these items are missing, an exception is thrown; otherwise, the attribute ensures that the content of the cookie and the input field match.
Next, let's construct the test view page.
3. Create View to protect CSRF
Now, right click the above first action Login to create a strong-typed view page named Login.cshtml. The related contents are given below.
The first point to notice is we've called the HTML Helper method AntiForgeryToken inside the <form/> block. This will create a hidden <input/> element and a related cookie on the user's machine.
Another point to notice is if there is only the attribute ValidateAntiForgeryToken specified in the action but not the corresponding HTML helper Html.AntiForgeryToken invocation in the above view page, then there will be a related HttpAntiForgeryException exception thrown out at the running time, with the message being "A required anti-forgery token was not supplied or was invalid".
4. Watch the running-time client-side source code
To make a contrast, let's first comment out the above two anti-forgery related operations to see what will happen at the running time. Listing 5 shows the related main source code (using the url "http://localhost:2047/customer/login"). For brevity, I've slightly edited it.
There is nothing peculiar here, just with ordinary HTML code.
Next, let's get rid of the above comments and run the sample again. This time, you will find the related source code like that in Listing 6.
Obviously, with the above change, a hidden <input/> element named __RequestVerificationToken is inserted into the form, with its value being the anti-forgery used token. At the same time, there is also a cookie named __RequestVerificationToken_Lw__ is generated with the same value as the hidden <input/> element. When the above form is submitted, they are both sent to server. This is all added by ASP.NET MVC framework to defend CSRF attacks.
In fact, we can also set a breakpoint at the second action Login to find out what really takes place in the behind scene. Figure 1 below illustrates the snapshot of the debug Watch window.
Figure 1: Track the cookie related stuffs during the course of debugging

As you've seen, the above snapshot shows the incoming request contains a cookie called __RequestVerificationToken_Lw__. And further, if you enter Request.Cookies[0] in the Watch window, you can look more closely at the cookie value and other related data.
On the other hand, on the client side, after submitting the form you can open up Firebug (we select Firefox 3.5 to run the sample application) to track the Request header structure. In this way, you will also catch sight of a cookie named __RequestVerificationToken_Lw__ that matches the previous one captured from the action method Login. Figure 2 illustrates the related snapshot in Firebug.
Figure 2: Track the anti-forgery related cookie from the client-side Firebug tool

If the server side action verifies via the authorization filter [ValidateAntiForgeryToken] that the incoming request has a Request.Form entry called __RequestVerificationToken and the request comes with a cookie of the corresponding name and their random values match, then the above submission and request will go through as normal. But if not, there will be an authorization failure with message "A required anti-forgery token was not supplied or was invalid". This prevents CSRF because even if a potential victim has a __RequestVerificationToken_Lw__ cookie, an attacker can't find out its value, so they can't forge a valid form post with the same value in the request.
Hence, there will be no trouble for the legitimate users to submit the form with the introduction of this anti-forgery action in ASP.NET MVC.
In fact, as hinted previously, if you remove the invocation to the HTML helper method AntiForgeryToken in the view page and run the sample again, you will surely meet an exception as shown in Figure 3 below.
Figure 3: A related exception will be thrown if conditions are not met

NOTEAlthough since ASP.NET MVC 1 the anti-forgery helpers have been introduced, there are some slight differences between the implementations of MVC 2/3 and MVC 1. For instance, ASP.NET MVC 2/3 adopted a newer data format to store the anti-forgery token. Therefore, if you deploy your upgraded application while visitors are actively using your site, their __RequestValidationToken_Lw__ cookies will suddenly become invalid, leading to HttpAntiForgeryException errors. Visitors won't be able to continue using your site until they clear their session cookies by closing and reopening their browsers. Therefore, for small applications, you can manually edit your global error handler page to display a related modesty and prominent message saying this. For larger Internet applications, though, this way may not be acceptable – you'd better think of a general solution for this awkwardness.
In the next section, we will continue with the anti-forgery related topic – salt.
Salt related story
Till now, we've only used the simplest form of the HtmlHelper method AntiForgeryToken. There are, in fact, still several forms of overrides for it (obtained via .NET Reflector):
First, the third form is the most common implementation compared with the preceding two. Second, the first one does not use a salt value. Slight different from the term "salt" in cryptology, salt here represents just an arbitrary string. A different salt value means a different anti-forgery token will be generated. So, even if an invader manages to get hold of a valid token somehow, he can't reuse it in other parts of the application where a different salt value is required. As you've guessed, for best security, we must keep the salt value secret.
As indicated before, all the three method will generate a hidden form field (anti-forgery token) that is validated when the form is submitted. Especially, in the third form the field value is generated using the specified salt value, domain, and path.
To use salt is simple. In the action method, you can write your action like this:
And in the view page, you can call the helper method like this:
In real scenarios, however, things are not as simple as told above. For example, one Web product might be deployed in many web servers. If a constant salt is evaluated in compile time, after the product is built and deployed to many clients, they all have the same salt. This will cause the clients' dislike and in some degree result in insecurity. I.e. these scenarios require generating salt at the runtime. To work around this, DiXin gave a better solution. And also, you will find in this great blog an Ajax related anti-forgery solution mentioned also in the previous section.
Can ASP.NET MVC prevent against all CSRF attacks?
The user-specific token policy can work well in blocking CSRF. However, there are still a few limitations we should be aware of:
- Legitimate users' browsers must open up Cookies; or else, the attribute
[ValidateAntiForgeryToken] will always deny their form posts.
- It works only with forms submitted as POST requests, not as GET requests. This isn't much of a problem if you follow the HTTP guidelines, which say that GET requests should be read-only.
- It's easily bypassed if you have any XSS vulnerabilities. Any such hole might provide a chance for an attacker to read any given victim's current
__RequestVerificationToken value, and then use it to forge a valid posting. Basically, if you have XSS, your CSRF-protection is a waste of time, so ensure you are not vulnerable to either.
Anti CRSF Tokens help prevent fishing attacks. However, they aren't meant to prevent spammers or web scrapers from running automated scripts against your web application. Again, bear in mind, that if your site suffers from other XSS vulnerabilities (where the privacy of your cookies or sessions are compromised) then Anti CRSF Tokens don't work at all.
The last thing to watch out for is around Flash and Silverlight. Both of these technologies do not subscribe to the same origin policy. Instead, they both use cross domain policy files to restrict access to remote resources. In another word, Flash/Silverlight script can only access resources on your site if you publish a cross domain policy xml file on your own site. If you do publish this file, you have to ensure allowing a white list of trusted third-party servers and never allow all.
Summary
In this article, we first introduced the Cross-site request forgery (CSRF) attack related concepts and corresponding actions to defense it. Then, we explored the ASP.NET MVC provided actions in beating CSRF through a detailed example. In fact, this article can only serve as an introductory story concerning CSRF attack. As you've seen, the CSRF attack is the result of how browsers handle cookies and cross domain form posts and is not specific to any one web platform. So, many web platforms may include their own mitigations to the problem.
The Experience ASP.NET MVC 3 Beta series
Part 1 In the coming ASP.NET MVC 3.0 a lot of new good things will be added or enhanced. In this article, we are going to focus upon the new view engine Razor to see how it will simplify the view design.
Part 2 In addition to the introduction of a new view engine Razor, ASP.NET MVC 3 Beta has also introduced numerous new HtmlHelpers, such as Chart, Crypto, WebGrid, WebImage, WebMail, etc. This article aims to introduce the two commonly-used new helper controls – WebGrid and Chart using relevant examples.
Part 3 In this installment, I'll first tell you a short story about unobtrusive JavaScript. Then, we'll delve into the unobtrusive client-side validation support. Finally, we will research into a more interesting story - the unobtrusive jQuery-Based Ajax support.
Part 4 In this article, we are going to continue to explore the other three important helpers - WebImage, WebMail, and Crypto.
Part 5 Starting from this article, let's explore some more advanced concepts and related utilizations associated with flexible Dependency Injection support introduced in ASP.NET MVC 3 Beta.
Part 6 In the last article, we've mainly discussed the new-styled DI support in ASP.NET MVC 3 Beta/RC in relation to the two new services - IControllerActivator and IViewPageActivator. Obviously, both of them are connected with controllers and views. In this article, however, we will shift our attention to the Model (generally called viewmodal in many blogs) related DI manipulations.
Part 7 Since ASP.NET MVC 1, CSRF (Cross Site Request Forgery) has been considered by introducing a set of anti-forgery helpers. In this article, we are to detail into CSRF related concepts and ASP.NET MVC's helper functions again CSRF.
Part 8 In this series of articles, we are going to explore as many as possible aspects of cache programming in the latest ASP.NET MVC 3 RC2 framework. And also, all the related samples have been tested against the latest ASP.NET MVC 3 RC 2.
Part 9 In the first part of this series, we've mainly explored Output Cache related issues. In this second part, however, we are going to delve into the general Data Cache topic.
About Xianzhong Zhu
 |
I'm a college teacher and also a freelance developer and writer from WeiFang China, with more than fourteen years of experience in design, and development of various kinds of products and applications on Windows platform. My expertise is in Visual C++/Basic/C#, SQL Server 2000/2005/2008, PHP+MyS...
This author has published 81 articles on DotNetSlackers. View other articles or the complete profile here.
|
You might also be interested in the following related blog posts
You should NOT use ASP.NET MVC if. . .
read more
New class: ASP.NET MVC Boot Camp developer training
read more
Six New Videos on ASP.NET Dynamic Data
read more
Will ASP.NET MVC be the main web UI platform for ASP.NET?
read more
The Wait is Over: ASP.NET 3.5 Extensions Preview Posted
read more
Joel Spolsky: Indigo won't enable a new class of applications
read more
|
|
Please login to rate or to leave a comment.