This is a 3 year old question with four different answers basically stating the same thing: Follow the norm, use tokens, don't try to use referer.
While tokens still is considered the most secure option, using the referer is often a lot easier, and is also pretty secure. Just be sure to look at all PUT/POST/PATCH/DELETE-requests and consider it an attack if a referer is missing or from the wrong domain. Really few (if any) proxies remove the referer for these kinds of requests.
See also the OWASP recommendation about checking the referer header as a CSRF protection:
Checking The Referer Header
Although it is trivial to spoof the referer header on your own
browser, it is impossible to do so in a CSRF attack. Checking the
referer is a commonly used method of preventing CSRF on embedded
network devices because it does not require a per-user state. This
makes a referer a useful method of CSRF prevention when memory is
scarce.
However, checking the referer is considered to be a weaker from of
CSRF protection. For example, open redirect vulnerabilities can be
used to exploit GET-based requests that are protected with a referer
check. It should be noted that GET requests should never incur a state
change as this is a violation of the HTTP specification.
There are also common implementation mistakes with referer checks. For
example if the CSRF attack originates from an HTTPS domain then the
referer will be omitted. In this case the lack of a referer should be
considered to be an attack when the request is performing a state
change. Also note that the attacker has limited influence over the
referer. For example, if the victim's domain is "site.com" then an
attacker have the CSRF exploit originate from "site.com.attacker.com"
which may fool a broken referer check implementation. XSS can be used
to bypass a referer check.
I use a simple js function like this
AddAntiForgeryToken = function(data) {
data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
return data;
};
Since every form on a page will have the same value for the token, just put something like this in your top-most master page
<%-- used for ajax in AddAntiForgeryToken() --%>
<form id="__AjaxAntiForgeryForm" action="#" method="post"><%= Html.AntiForgeryToken()%></form>
Then in your ajax call do (edited to match your second example)
$.ajax({
type: "post",
dataType: "html",
url: $(this).attr("rel"),
data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
success: function (response) {
// ....
}
});
Best Answer
To add to osoviejo's excellent answer, the instructions below, from my recent blog post on CSRF, put his work together with the information in Phil's blog in one comprehensive answer.
ASP.NET/MVC provides a mechanism for this: you can add to to a collection of filters on the global
FilterProviders
object. This allows you to target some controllers and not others, adding the needed security feature.First, we need to implement an IFilterProvider. Below, you can find Phil Haack's Conditional Filter Provider class. Begin by adding this class to your project.
Then, add code to Application_Start that adds a new
ConditionalFilterProvider
to the global FilterProviders collection that ensures that all POST controller methods will require the AntiForgeryToken.If you implement the two pieces of code above, your MVC application should require the AntiForgeryToken for every POST to the site. You can try it out on Phil Haack's CSRF example web site - once protected, the CSRF attack will throw
System.Web.Mvc.HttpAntiForgeryException
without having to add the[ValidateAntiForgeryToken]
annotation. This rules out a whole host of "forgetful programmer" related vulnerabilities.