CSRF attacks are one of the many security issues that web developers must defend against. Fortunately, ASP.Net MVC makes it easy to defend against CSRF attacks. Simply slap on [ValidateAntiForgeryToken] to every POST action and include @Html.AntiForgeryToken() in every form, and your forms will be secure against CSRF.
However, it is easy to forget to apply [ValidateAntiForgeryToken] to every action. To prevent such mistakes, you can create a unit test that loops through all of your controller actions and makes sure that every [HttpPost] action also has [ValidateAntiForgeryToken].
Since there may be some POST actions that should not be protected against CSRF, you’ll probably also want a marker attribute to tell the test to ignore some actions.
This can be implemented like this:
First, define the marker attribute in the MVC web project. This attribute can be applied to a single action, or to a controller to allow every action in the controller.
///<summary>Indicates that an action or controller deliberately
/// allows CSRF attacks.</summary>
///<remarks>All [HttpPost] actions must have
/// [ValidateAntiForgeryToken]; any deliberately unprotected
/// actions must be marked with this attribute.
/// This rule is enforced by a unit test.</remarks>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class AllowCsrfAttacksAttribute : Attribute { }
Then, add the following unit test:
[TestMethod]
public void CheckForCsrfProtection() {
var controllers = typeof(MvcApplication).Assembly.GetTypes().Where(typeof(IController).IsAssignableFrom);
foreach (var type in controllers.Where(t => !t.IsDefined(typeof(AllowCsrfAttacksAttribute), true))) {
var postActions = type.GetMethods()
.Where(m => !m.ContainsGenericParameters)
.Where(m => !m.IsDefined(typeof(ChildActionOnlyAttribute), true))
.Where(m => !m.IsDefined(typeof(NonActionAttribute), true))
.Where(m => !m.GetParameters().Any(p => p.IsOut || p.ParameterType.IsByRef))
.Where(m => m.IsDefined(typeof(HttpPostAttribute), true));
foreach (var action in postActions) {
//CSRF XOR AntiForgery
Assert.IsTrue(action.IsDefined(typeof(AllowCsrfAttacksAttribute), true) != action.IsDefined(typeof(ValidateAntiForgeryTokenAttribute), true),
action.Name + " is [HttpPost] but not [ValidateAntiForgeryToken]");
}
}
}
typeof(MvcApplication) must be any type in the assembly that contains your controllers. If your controllers are defined in multiple assemblies, you’ll need to include those assemblies too.
Other posts
-
A _read-only_ object is an object that does not expose any way to change it....
-
{% assign openTag = '{%' %} [Last time]({% post_url 2013-06-09-writing-about-jekyll-in-jekyll %}), we saw how to...
-
[Jekyll](http://jekyllrb.com) is a very nice system for writing blogs. However, it does have some shortcomings,...
-
The next step in [migrating my blog to Jekyll]({% post_url 2013-05-31-migrating-from-blogger-to-jekyll %}) was to convert...
-
The first step in my migration to Jekyll was to import my old posts into...
-
My new design is powered by Jekyll and LESS (the LESS does as much or...
-
After nearly a year of inactivity, I have finally returned to my blog. I had...
-
{% raw %} If you open an older ASP.Net MVC3 project in Visual Studio 2012,...
-
{% raw %} Last year, Microsoft announced a simple new feature in C# 5: Caller...
-
{% raw %} If you use the ASP.Net MVC 3 [Compare] validation attribute on a...
-
This post
-
What’s wrong with the following code? var names = new HashSet<string>(StringComparer.OrdinalIgnoreCase); ... if (names.Contains(sqlCommand.ExecuteScalar()) This ...
-
One common misconception about web security is that protecting important actions with CAPTCHAs can prevent XSS...
-
One of the most useful additions to the .Net 4.0 base class library is the...
-
ASP.Net MVC uses the new (to ASP.Net 3.5) Http*Base wrapper classes (HttpContextBase, HttpRequestBase, HttpResponseBase, etc)...
-
People sometimes wonder why C# 5 needs to add caller info attributes, when this information...
-
UPDATE: Now that the Visual Studio 11 beta has shipped with this feature implemented, I...
-
UPDATE: Now that the Visual Studio 11 beta has shipped with this feature implemented, I...
-
UPDATE: Now that the Visual Studio 11 beta has shipped with this feature implemented, I...
-
One common question about ASP.Net MVC is how to make “default” controller. Most websites will...
-
Update: This bug was fixed in XRegExp 1.5.1. However, as far as I know, there...
-
Part 1 is here Some languages have better ways to pass boolean parameters. C# 4.0,...
-
Have you ever written code like this: public void UpdateLayout(bool doFullLayout) { //Code if (doFullLayout)...
-
C# is usually touted as a type-safe language. However, it is not actually fully type-safe!...
-
Until now, I've been focusing on only one of the differences between delegates and function...
-
When working with large .Net applications, it can be useful to find out where event...
-
A .Net event actually consists of a pair of accessor methods named add_EventName and remove_EventName. ...
-
Sometimes, it can be useful to make an extension method specifically for a single block...
-
Unlike WinForms or native Win32 development, WPF provides a rich layout model which allows developers...
-
This is part 5 in a series about state and function pointers; part 1 is...
-
This is part 4 in a series about state and function pointers; part 1 is...
-
.Net supports two kinds of delegates: Open delegates and closed delegates. When you create a...
-
This is part 3 in a series about state and function pointers; part 1 is...
-
This is part 2 in a series about state and function pointers; part 1 is...
-
Most languages – with the unfortunate exception of Java – allow functions to be passed...
-
Many people write ForEach extension methods for MVC WebForms views, which take a sequence and...
-
Razor’s inline helpers allow you to create lambda expression that return markup (as a HelperResult). ...
-
In addition to normal and static helpers, Razor supports inline helpers, (also known as templates),...
-
Razor helpers can be extremely useful, but they are designed to be used only by...
-
The Boot Camp drivers in the latest generation of MacBook Pros now expose more of...
-
We’ll continue our trek into Razor’s class-level features with helpers. Helpers are one of Razor’s...
-
After looking at how Razor’s Execute() method is generated, we will turn to class-level features....
-
Last time, we saw how basic Razor constructs are translated into C#. We can see...
-
After looking at the various assemblies in the WebPages framework, we will drill into the...
-
Last time, we saw how standalone Razor pages are served. MVC3 maintains the strict separation...
-
Last time, we saw that ASP.Net Web Pages are implemented in two independent assemblies. These...
-
Razor involves two distinct components: The Razor engine and the WebPages framework. The Razor engine,...
-
jQuery makes it very easy to modify a DOM tree. For example, to strip all...
-
Last time, we saw that there are severe limitations in creating ASPX pages which inherit...
-
ASP.Net pages can inherit from custom classes (as long as they inherit System.Web.UI.Page). This can...
-
.Net developers frequently need to build connection strings, especially when connecting to Access or Excel...
-
One of the unique features of ASP.Net WebPages (formerly Razor) is automatic HTML encoding. All...
-
C# 4.0 adds support for optional parameters. The following code prints 4: static void Main()...
-
The new ASP.Net WebPages view engine (formerly Razor) allows you to create reusable parameterized blocks...
-
.Net DataTables can be very useful when writing data-driven applications. However, they have one limitation:...
-
When designing fluent APIs, one issue that comes up is partial type inference. If a...
-
A common chore in developing real-world C# applications is implementing value semantics for equality. This...
-
Last time, we saw that the this parameter to an instance method in a struct...
-
Usually, you cannot pass ref this as a parameter, since this is not a writable...
-
VB.Net’s Nothing keyword is is not the same as C#’s null. MSDN states, “Assigning Nothing...
-
jQuery contains a powerful and flexible animation engine. However, it has some limitations, primarily due...
-
A generic class can specify that its generic parameter must inherit a type. However, there...
-
In part 1, we discussed the simple approach to making a nested iterator. However, we...
-
C# 2.0 introduced a powerful feature called an iterator, a method which returns an IEnumerable<T>...
-
My previous post stretched the limit of simple copy prevention. Beyond this point, it gets...
-
The methods discussed in my previous post are crude and ugly. Most of the time,...
-
Many web developers like to prevent their viewers from copying their text. While I do...