Josh Josh - 3 months ago 38 Question

Protect against CSRF attacks in ASP.NET Web Forms without Master Pages

I'm reviewing the security of an ASP.NET website that is about 7 years old. At the time the site was created the Microsoft guidance was to add the following to a common Base Page (inherited by all code behind pages):

Protected Overrides Sub OnInit(ByVal e As System.EventArgs)

If Request.IsSecureConnection = True Then
ViewStateUserKey = Session.SessionID
End If
End Sub

This advice comes from the following MSDN Article from 2005.

My question is if this is still a valid and effective technique to protect against CSRF attacks.

Note, I read an SO question about this topic, but it appears the Visual Studio 2012+ project auto generated protection for CSRF are added to Master Pages. The site I'm reviewing doesn't use Master Pages because of CSS conflicts, and it is not in scope to add Master Pages into the current update.


Yes, this will mitigate CSRF if ViewStateMac is enabled.

This is because each individual user will have the ViewState authenticated by their own key (which is session ID).

As the ViewState is POSTed back to the server upon every request that has side-effects, ASP.NET will validate that the ViewState value is in fact from the current user.

Therefore any attacker cannot construct a POST request to entice their victim to submit because they do not have their victim's session ID in order to do this.

Note that the above assumes that all requests that have side-effects are done via postbacks. That is, the application is following RFC 7231 in regards to the definition of "safe" methods and there are no other handlers for POST requests other than the postback mechanism.

Note that any custom AJAX requests in the application, such as those made by JQuery will not be protected from CSRF because these are not implemented as postbacks.

Setting and checking a custom header for these is recommended, like X-Requested-With. Note that due to various Flash vulnerabilities, you may want to also pass a token into the header to check server-side.