Search code examples
securitywebcsrfcsrf-protection

Why do browsers allow CSRF?


I am pretty new to web security, and as I read more about the different attack vectors, my mind boggles that they are allowed in the first place. It's like the web was designed with a broken security model and to be vulnerable.

I am also amazed at the amount of vague and imprecise information. For example, at first the Single Origin Policy sounds pretty good, then I read that it only applies to XHR, and oh and by the way, doesn't actually prevent XHR cross-origin POST, which is the classic CSRF attack. Glad I kept reading.

There is also an Origin header that the server can use to make sure the request is coming from the right place -- but oops, it is set inconsistently across browsers, and if it is NOT set, you can't be quite sure if it was because of a same-origin request, or a request type that just didn't get it for certain browsers (maybe an IMG tag?). Keep reading.

So the right way seems to be set a CSRF token in the session cookie, and also add that token to forms/links, and then compare them server side on a submission. In theory (and lets exclude all XSS attacks for the purpose of this question), a CSRF attempt from another tab may make a POST request to a form that includes the cookie, but without a form input element set to the matching token (because it can't read the token from the cookie), so the server will reject the request. Works but kludgy, and make sure you never ever forget to check!

Holding that thought in mind for a second, here is my question -- why does the browser send the session cookie in a request that originates from a page that is not the origin of the cookie?

I mean, browsers will refuse to send cookies to different domains for good reason, but are quite happy to send them from different origins? Would stuff break if they didn't? Would it be a robust defence against CSRF, only requiring servers to do what they are doing anyway -- checking for a valid session cookie?

Edit: maybe this is an attempt to improve the situation? https://datatracker.ietf.org/doc/html/draft-west-origin-cookies-01


Solution

  • I am pretty new to web security, and as I read more about the different attack vectors, my mind boggles that they are allowed in the first place. It's like the web was designed with a broken security model and to be vulnerable.

    All true. It was never designed to be secure in the first place. The web was originally designed as a static document management and sharing system which allowed direct links to resources on different machines.

    The dynamic web you see today is a kludge. We can fix it with CSRF tokens, HTTP headers and the like, but if you make a dynamic website without doing any of these things then chances are it's vulnerable (and keeps people like me in a job).

    Check out its history in the Wikipedia article.

    I am also amazed at the amount of vague and imprecise information. For example, at first the Single Origin Policy sounds pretty good, then I read that it only applies to XHR, and oh and by the way, doesn't actually prevent XHR cross-origin POST, which is the classic CSRF attack. Glad I kept reading.

    Also mainly true. The Same Origin Policy also applies to windows and frames too (e.g. example.com cannot alter the content of example.org by JavaScript if example.com includes an IFrame to example.org). Yes, cross-domain XHR's can be made, but without CORS being enabled the responses cannot be read. This does protect CSRF tokens from being stolen, but as you say if you're not using CSRF protection then this presents a CSRF vulnerability.

    Other defences such as adding a custom header can be used to mitigate CSRF, as custom headers cannot be sent cross-domain.

    XHRs didn't used to be able to access anything cross-domain, which was seen as too big a restriction, hence the advent of CORS. Previously, as forms could access different domains anyway, it was not seen as a particularly risky maneuver. It is still not, provided the appropriate controls are put into place.

    There is also an Origin header that the server can use to make sure the request is coming from the right place -- but oops, it is set inconsistently across browsers, and if it is NOT set, you can't be quite sure if it was because of a same-origin request, or a request type that just didn't get it for certain browsers (maybe an IMG tag?). Keep reading.

    Quite true. See this answer.

    why does the browser send the session cookie in a request that originates from a page that is not the origin of the cookie?

    Because lots of things would break otherwise. There are countless forms that are designed to be submitted from static sites to dynamic sites that do the back-end handling.

    There is a new standard for "same-site" cookies. A less dry explanation is here.

    Basically cookies can be set with a new attribute SameSite. In strict mode, cookies are not sent when the site is different. In lax mode, they are only withheld if the method is e.g. POST, which is where CSRF vulnerabilities mainly lie.

    The one you linked to was an early draft of this.