Search code examples
firebasesecuritywebcsrf

Should a CSRF check be done on all post requests?


As far as I understand it a CSRF check should be done on any requests that change the state.

If this is the case shouldn't all POST requests have a CSRF check?

If this isn't the case what exceptions are there?

The origin of this question is from a tutorial on Managing Session Cookies with Firebase, they use CSRF checks for the initial login step but not for a post request later

https://firebase.google.com/docs/auth/admin/manage-cookies#node.js_2


Solution

  • TL;DR:

    1. CSRF protection should be implemented on any state-changing request, regardless of the HTTP method used (although PUT and DELETE requests sort of inherently mitigate CSRF)
    2. To protect against CSRF use one of the methods described in the numbered list below.

    Details:

    As you mentioned, in a CSRF attack an attacker looks to perform a state-changing operation such as modifying the profile's email address, transferring money, etc.

    Any post-authentication request that triggers any operation on the server should be validated. Implementing CSRF protection on a log-in screen makes no sense as the attacker would need to know the user's password, and if he knows the users password the CSRF attack is redundant. (Disclaimer - in some edge-cases such as chaining with self-XSS, CSRF on a login screen could assist an attacker)

    Requests that simply return data but do not perform any action, do not require CSRF protection as in a CSRF attack the attacker won't have access to the server's response.

    CSRF attacks are made possible because cookies are automatically sent by the browser to the corresponding domain, without requiring any programmatic trigger or user interaction. Which also means that putting a CSRF token in a cookies makes no sense and won't actually mitigate CSRF.

    Mitigations:

    That said, there is more than one way to mitigate CSRF attacks:

    1. Use anti-CSRF tokens - a unique, random value typically stored as a hidden field as part of the HTML form that sends the request. The value should be unique per page or at least per user session and validated by the server on each state-changing request.
    2. Use session tokens stored in web storage (sessionStorage/localStorage) rather than cookies. Since these values will need to be programmatically sent, typically via some SPA framework and are not sent automatically, this by default defeats CSRF.
    3. Implement the "sameSite" flag on session cookies.