Difference between CSRF and X-CSRF-Token

  • What is the difference between use X-CSRF-Token in an HTTP header or token in the hidden field?
  • When to use the hidden field and when to use the header and why?

I think that X-CSRF-Token is when I'm using JavaScript / AJAX but I'm not sure.


Solution 1:

CSRF protection comes in a number of methods.

The traditional way (the "Synchronizer token" pattern) usually involves setting a unique valid Token value for each request and then verifying that unique value when the request is subsequently sent in. It is usually done by setting a hidden form field. The token value is usually short lived and associated to that session, so if a hacker tries to reuse a value they saw previously on the page, or tries to guess the value they will likely fail. So only requests from your application will work and forged requests from outside your application/domain (aka cross site request forgery) will fail.

The downside of that is it requires your application to set this hidden token on all HTML forms. These pages now have to be dynamically generated by an application, when perhaps previously they were static HTML. It can also break the back button (as you need to refresh the form to regenerate another unique CSRF value). You also now need to keep track of valid tokens on the server side and check any requests use a valid token. This can take quite a bit of extra effort to implement and maintain going forward.

An alternative approach (called the "Cookie-to-header token" pattern) is to set a Cookie once per session and the have JavaScript read that cookie and set a custom HTTP header (often called X-CSRF-TOKEN or X-XSRF-TOKEN or just XSRF-TOKEN) with that value. Any requests will send both the header (set by Javascript) and the cookie (set by the browser as a standard HTTP header) and then the server can check that value in the X-CSRF-TOKEN header matches the value in the cookie header. The idea being that only JavaScript run on the same domain would have access to the cookie, so JavaScript from another domain couldn't set this header to the right value (assuming the page is not vulnerable to XSS that would give access to this cookie). Even fake links (e.g. in a phishing email) would not work either, as even though they would appear to come from the right domain, only the cookie will be set but not X-CSRF-TOKEN header.

This can be MUCH easier to implement than the Synchronizer token pattern as you don't need to set the token for each call to each form, and the check is relatively simple too (just check the cookie matches the header) rather than tracking CSRF tokens validity. All you need is to set a cookie to a random value for each session. Some front end frameworks will even automatically generate the header for you if they see the cookie (e.g. AngularJS does this for example).

The downside is that it requires JavaScript to work (but that may not be an issue if your app basically doesn't work without JavaScript anyway) and also it will only work for requests the JavaScript makes (e.g. XHR requests) - regular HTML form requests would not set the header. A variation on this (the "Double Submit Cookie" pattern) puts the X-CSRF-TOKEN value in a hidden form field rather than in an HTTP Header to get around this but still keep the server side logic simpler than the traditional Synchronizer token pattern. It should be noted however that OWASP states some weaknesses with the Double Submit method, when the attacker is able to set the cookie (which is often easier than reading the cookie) so recommends validating the CSRF token in this case.

Additionally the Synchronizer token pattern can allow extra controls to enforce flow (e.g. the hidden field CSRF token will only be set when the application thinks you have sent a valid request in to get that form).

Oh and some security scans will pick up the fact the cookie is not set with the HTTP-Only flag so can be read by JavaScript - but that's deliberate as it needs to be able to read by that! False alert. You'd think as long as you are using a common name like X-CSRF-TOKEN they would know not to flag this, but have seen it flagged often.

Solution 2:

All of them are for cross site request forgery protection and you need to use just one of them when sending a request to backend. Different names comes from different frameworks.

It's all about sending a csrf value to backend. Then backend will compare it with the csrf value stored in database for that specific user.


csrf:

  • Is used in HTML forms (not AJAX)
  • Produced in backend while rendering HTML form.
  • we can not set request header in HTML forms directly, so we have to send it via form input as a hidden field.
  • you can name this hidden input whatever you want.
    E.g.: <input name="my_csrf_input" value="a_hashed_string(the csrf value)"

X-CSRF-TOKEN:

  • It is added to the request HTTP header for AJAX requests.
  • To use it, we can put the csrf value in a <meta> tag while rendering the HTML, then in front end we can get the value from that <meta> tag and send it to backend.

Laravel specific:

  • When using Laravel as backend. Laravel checks this header automatically and compares it to the valid csrf value in database (Laravel has a middleware for this).

X-XSRF-TOKEN:

  • It is added to the request header for AJAX requests.
  • Popular libraries like Angular and Axios, automatically get value of this header from XSRF-TOKEN cookie and put it in every request header.
  • To use it, we should create a cookie named XSRF-TOKEN in backend, then our front end framework that uses Angular or Axios will use it automatically.

Laravel specific:

  • Because it's popular, Laravel creates this cookie in each response.
  • so when you're using for example Axios and Laravel you don't need to do anything, just log user in and 'auth' middleware will do the job.
  • It's a bigger string compared to X-CSRF-Token because cookies are encrypted in Laravel.