Search code examples
asp.net-mvcformspostcsrfantiforgerytoken

Unexpected behaviour with AntiForgeryToken and ValidateAntiForgeryToken


I've started using AntiForgeryToken in some of my forms to prevent cross site request forgery. However I am getting some weird behaviour and just wanted to clarify whether this is a bug or just me doing something wrong. I am using the Html.AntiForgeryToken() call in my form. I then use the [ValidateAntiForgeryToken] attribute in the action method that the form posts to. I'm not using a salt at this point.

My understanding is that Html.AntiForgeryToken() generates a hidden input with a name of __RequestVerificationToken and a cookie named __RequestVerificationToken_Lw__, which should both contain the same value.

The behaviour I am experiencing however is that:

  1. The cookie always has the same value no matter how many times you GET the page
  2. The hidden input has a different value every time you GET the page
  3. The ValidateAntiForgeryToken validates every time, even from a different site in a CSRF scenario.
  4. If I change the value of the hidden input in the foreign site, the token doesn't validate (expected behaviour, but why does it validate when the hidden input/cookie value is different?)

Anyone got any ideas?


Solution

  • For number 3, are you including the hidden field in your CSRF scenario?

    The safety of the AntiForgeryToken is that the hidden input exists only in the page served by your domain, and cannot be copied or captured by another domain. If you have mocked up a test which passes the hidden input, then that is not a valid test.

    I suggest you read this article from Phil Haack: Anatomy of a Cross-site Request Forgery Attack