ASP MVC and XSRF
This post is part of the series 'Vulnerabilities'. Be sure to check out the rest of the blog posts of the series!
- Impersonation and security
- SQL injections
- How to prevent CSRF attacks
- ASP MVC and XSRF (this post)
- Cross-site scripting (XSS)
- ASP MVC: Mass Assignment
- Regex - Deny of Service (ReDoS)
- Deserialization can be dangerous
- Prevent Zip bombs in a .NET application
- Prevent Zip Slip in .NET
- How to protect against XML vulnerabilities in .NET
ASP MVC provides a simple method to protect against XSRF attacks . Indeed, you just have to add the following line in the form:
@Html.AntiForgeryToken()
And the ValidateAntiForgeryToken
attribute in the controller:
[ValidateAntiForgeryToken]
public ActionResult Create(Model model)
This will add a hidden field to the page and a cookie. When submitting the form, ASP.NET MVC will validate the value of them:
<input name="__RequestVerificationToken" type="hidden" value="geGaItAfh7cil98mAt38y3ymsCsINWs1lH9cZY52lSjZ_bCU3vTgmS8IqONXJo6rLqjAI3pnf9IyUu2O9XGS_NsiSCzhbYy3wI4IeEX6WiQ1"/>
__RequestVerificationToken : 5qqXHEEfzDa_Jn7glEmgtOP586KRLlXOSpyznXvkMooZvQjI9fmDtQ9MH07eIt2vQhBcD44lpRLmMbjTFkkh6H081thqTpdfJ6F3VFLJ0Kw1
The problem is that it is easy to forget the attribute. Therefore, I write a unit test to check that each method using the Post method is decorated with the ValidateAntiForgeryToken
attribute:
[TestMethod]
public void PostMethodShouldBeDecoratedWithValidateAntiForgeryAttribute()
{
var controllers = typeof(MvcApplication /* Could be any type from the project */).Assembly.DefinedTypes.Where(t => typeof(ControllerBase).IsAssignableFrom(t));
foreach (var controller in controllers)
{
controller.Methods()
.ThatReturn<ActionResult>()
.ThatAreDecoratedWith<HttpPostAttribute>()
.Should()
.BeDecoratedWith<ValidateAntiForgeryTokenAttribute>("because all Actions with HttpPost require ValidateAntiForgeryToken");
}
}
This test uses the FluentAssertions library .
Or if you do not want to use this library
[TestMethod]
public void PostMethodShouldBeDecoratedWithValidateAntiForgeryAttribute()
{
var controllers = typeof(MvcApplication).Assembly.DefinedTypes.Where(t => typeof(ControllerBase).IsAssignableFrom(t));
foreach (var controller in controllers)
{
foreach (MethodInfo method in controller.GetMethods())
{
if (method.GetCustomAttribute<HttpPostAttribute>() != null)
{
Assert.IsNotNull(method.GetCustomAttribute<ValidateAntiForgeryTokenAttribute>(), string.Format("Method {0}.{1} should be decorated with ValidateAntiForgeryTokenAttribute.", controller.Name, method.Name));
}
}
}
}
And there you have no more excuses.
Do you have a question or a suggestion about this post? Contact me!