27

If I understand correctly, in a CSRF attack a malicious website A tells my browser to send a request to site B. My browser will automatically include my B cookies in that request. Although A cannot see those cookies, if I'm already authenticated in B the request will look legit, and whatever action was asked will be successfully performed. To avoid this, every time that I visit a page of B containing a form, I receive a CSRF token. This token is associated to my session, so if I make a POST to B I MUST include such token; otherwise B rejects my request. The benefit of this scheme is that A will not have access to that token.

I have two questions:

  • Is the above description correct?
  • If so, why can't site A first tell my browser to send a GET to B, obtain the CSRF token from the response, and then use the token to send now a POST to B? Notice that the token will be valid and associated to my session, as the GET also contains all my B cookies.

Thanks!

thelastone
  • 475
  • 4
  • 11

2 Answers2

17

Your description is correct.

If site A tells your browser to go to B and get the token, that's fine, but as it is a cross-domain request, A will not have access to the token in Javascript (this is a browser feature). So when A tells your browser to go back to B and actually do something, it still cannot include the token in the request.

That is, unless B set the token as a cookie. Evidently, that would be flawed, because the token cookie would also be sent, thus negating any protection. So the token in this case must be sent as either a form value or a request header (or something else that is not sent automatically like a cookie).

This also means that if B is vulnerable to cross-site scripting, it is also vulnerable to CSRF, because the token can then be stolen, but CSRF is the smaller problem then. :)

Gabor Lengyel
  • 14,129
  • 4
  • 32
  • 59
  • 2
    Thanks for the answer. What I don't quite understand yet is this "browser feature" (I imagine you refer to CORS). Because there are many sites that perform cross-domain requests, and they can actually look at the content of the response. The most simple example I can think of is the inclusion of an image which src points to a different domain. What I don't get is if the server will send a different Access-Control-Allow-Origin header for images than for pages, or if the browser is taking care of this. Thanks again. – thelastone Nov 28 '16 at 12:11
  • 6
    Actually the feature is called SOP, same origin policy. Javascript only has access to content downloaded from the origin of the page itself, unless the other site sends CORS (cross-origin resource sharing) headers to allow the requestor access. Javascript does not have access to cross-origin images either, but they are displayed to the user. Similarly, another origin can be loaded and displayed in an iframe (unless x-frame-options is sent, but that's a different story), but the outer page will not have access to the iframe contents. – Gabor Lengyel Nov 28 '16 at 12:58
  • It's a browser feature. Can an attacker use something else, may be like curl and send request to siteB and fetch csrf token ? – node_analyser Apr 01 '21 at 12:42
  • 1
    @v1h5 yes of course, for himself. But would that make sense? No, he would have it in a browser anyway. In CSRF the attacker exploits the existing session of a valid user (victim) because for example the session cookie is sent automatically. In curl he wouldn't have a valid user. – Gabor Lengyel Apr 01 '21 at 13:21
  • 1
    @GaborLengyel oh yes! that makes sense. Apologies for lame question. Trying my best to understand all the basics. – node_analyser Apr 01 '21 at 13:52
0

Correct.

Site A can't get site B's csrf token because of the browser's CORS strategy.

And we need to validate the request's referer(It can be forged). https://en.wikipedia.org/wiki/HTTP_referer

It is also a good practice to validate the crsf token in url(AKA query string).

FYI,Laravel, a popular web framework, uses a hidden CSRF token field in the form to prevent csrf attack.

solarhell
  • 172
  • 8
  • I know about the hidden CSRF token, that is precisely what I refer to in my question. So, if I understand correctly, the attack I mention is prevented by telling the server to disallow sending responses containing CSRF tokens to requests from other referrers (which the browser should ensure is correct, right?). – thelastone Nov 28 '16 at 11:08
  • @Mugarte Bingo. – solarhell Nov 28 '16 at 12:31