CSRF tokens are used a lot.

The server sets a token in cookie for that domain that either (1) include in the HTML form or (2) Javascript can read and include in the request. The server verifies the token in the request matches the token in the cookie.


But why not simply check the Origin header? According to OWASP, that's why it exists:

The Origin HTTP Header standard was introduced as a method of defending against CSRF and other Cross-Domain attacks.

"Is the Origin not there? If not, OK. If it is, is it one one I trust (e.g. the same origin)? If so, OK."


CSRF tokens can be troublesome. They are

  • more difficult for beginners to understand -- "Wait...I send it twice? What's CRSF again?"
  • requires cookies (granted, not usually a problem)
  • more difficult to implement -- needs controller and view
  • less flexible -- can't ever work cross-domain
  • strange in non-web settings -- "Why does your API need a CSRF token?" "Oh, 'cause JS uses that too."
  • more cumbersome to implement globally -- "Oops, forgot the CSRF tag here among my 25 HTML form fields"

Given these disadvantages, why are CSRF tokens so commonly used, rather than the Origin header?

  • 1
    stackoverflow.com/questions/24680302/… Here is a similar question. – sir_k Dec 8 '14 at 9:15
  • CSRF tokens are the best method to prevent CSRF vulnerabilities. There are other checks that help with prevention like the origin header, different types of challenges, and checking the referrer header. While these methods can help with prevention, none of them are as effective as tokens. – Paraplastic2 Dec 8 '14 at 13:56
up vote 6 down vote accepted

You can't currently depend on the Origin header, because it is not implemented in all browsers which are in active use. Apart from that, Origin is not sent in all cases relevant to CSRF, like

<img src=http://router/admin.cgi?...>
  • @PaulDraper: just tested with latest Chrome and Firefox. Both don't sent an Origin header if including an image from a remote site. But this is a typical vector for CSRF. – Steffen Ullrich Dec 8 '14 at 13:34
  • Hm....it would seem inappropriate then for OWASP to recommend it, right? "This section details other ways that an application can prevent CSRF by relying upon similar rules that CSRF exploits can never break...Checking The Origin Header". – Paul Draper Dec 8 '14 at 14:04
  • 2
    @PaulDraper: it does not say that you can rely on the Origin header to exist, only "If the origin header is present, then it should be checked for consistency." – Steffen Ullrich Dec 8 '14 at 14:08
  • 1
    @PaulDraper Strictly speaking, I think if you treat a lack of origin as a failed origin-match, a CSRF attack can't break your security, but your website may still break (i.e., fail to function normally for browsers that never send Origin headers) without an attack. An attack doesn't break your site; the browser's failure to send an Origin header breaks your site. That's obviously not great site design, but that's only reading of "rules that CSRF exploits can never break" I can think of that is strictly correct. – apsillers Dec 8 '14 at 14:08
  • 2
    Since GET is a safe operation (as defined the HTTP standard), I suppose checking the Origin header would be sufficient for preventing non-safe operations from any modern browser to a standards-compliant server. That is sufficient in my case. – Paul Draper Jan 30 '15 at 1:08

"Is the Origin not there? If not, OK. If it is, is it one one I trust (e.g. the same origin)? If so, OK."

Although you can use the Origin header to reject a request. If the Origin header is missing, you cannot safely accept it, even for POST requests. As far as I know, an HTML form request doesn't include an Origin header, and neither do imgs, scripts, links, cos background images, or other places that make get requests. And of course the Origin header isn't sent for XHR requests on the same host, so you need another protection mechanism.

One option is to put the csrf token in a custom header, which is easier to do globally and doesn't put the token in the URL for get requests. And then if desired you can check that the request either has the Origin header or custom header.

You might also be able to do something like the method you mentioned, provided you reject any request that isn't an Ajax request. But I am not as confident about the security of that.

In short the Origin header, by itself isn't enough if you want to make same-origin requests, but could be used in combination with another csrf protection method.

  • It would seem that for form POSTs, some browsers include the Origin header, but others do not. It does seem incongruous with OWASP: "This section details other ways that an application can prevent CSRF by relying upon similar rules that CSRF exploits can never break." – Paul Draper Jul 29 '15 at 14:33
  • And if it is not present? – Paul Draper Jul 29 '15 at 14:40
  • "If the origin header is present, then it should be checked for consistency." OWASP doesn't say it is safe to accept requests without an Origin header, merely that if the header is present it can't be broken by CSRF. The section on using the referrer header states that if it is missing it must be rejected – Thayne Jul 29 '15 at 14:43
  • There is the potential for vulnerability if even one browser doesn't send the header. – Thayne Jul 29 '15 at 14:44
  • 1
    Yeah, it certainly does seem like a subpar recommendation. – Paul Draper Jul 29 '15 at 17:35

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.