Why can't a malicious site obtain a CSRF token via GET before attacking?
Asked Answered
S

2

31

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!

Simulate answered 28/11, 2016 at 9:51 Comment(1)
The Same-origin Policy prevents site B from reading content on Site A as the userAkerley
R
18

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. :)

Regime answered 28/11, 2016 at 11:15 Comment(5)
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.Simulate
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.Regime
It's a browser feature. Can an attacker use something else, may be like curl and send request to siteB and fetch csrf token ?Shawm
@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.Regime
@GaborLengyel oh yes! that makes sense. Apologies for lame question. Trying my best to understand all the basics.Shawm
L
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.

Leporide answered 28/11, 2016 at 10:42 Comment(2)
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?).Simulate
@Mugarte Bingo.Leporide

© 2022 - 2024 — McMap. All rights reserved.