74

If CORS is properly setup on a server to only allow a certain origins to access the server,

Is this enough to prevent CSRF attacks?

Abilogos
  • 4,777
  • 2
  • 19
  • 39
programmerdave
  • 1,088
  • 1
  • 9
  • 17
  • Good to read: https://security.stackexchange.com/a/97938/108639 and https://poshai.medium.com/are-csrf-tokens-necessary-3a6976bf1f34 – Adam Apr 09 '21 at 10:23
  • Really an authentic question you have asked. tnx for the question – Abilogos Oct 16 '21 at 17:22
  • 1
    Another good read: https://nodeployfriday.com/posts/cors-cyber-attacks/ – Colm Bhandal May 18 '22 at 09:08
  • Related question about the topic of alternative-to-CSRF-token: [security - Is checking the referrer enough to protect against a CSRF attack? - Stack Overflow](https://stackoverflow.com/questions/1413930/is-checking-the-referrer-enough-to-protect-against-a-csrf-attack) – user202729 May 21 '22 at 17:51

6 Answers6

66

To be more specific, it is easy to make the mistake of thinking that if evil.example cannot make a request to good.example due to CORS then CSRF is prevented. There are two problems being overlooked, however:

  1. CORS is respected by the browsers only. That means Google Chrome will obey CORS and not let evil.example make a request to good.example. However, imagine someone builds a native app or whatever which has a form that POSTs things to your site. XSRF tokens are the only way to prevent that.

  2. Is it easy to overlook the fact that CORS is only for JS request. A regular form on evil.example that POSTs back to good.example will still work despite CORS.

For these reasons, CORS is not a good replacement for XSRF tokens. It is best to use both.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
aleemb
  • 31,265
  • 19
  • 98
  • 114
  • 35
    If I'm not mistaken, your first point may be invalid -- since CSRF attacks only work on browsers. – ineedahero Dec 14 '16 at 16:36
  • 4
    as @ineedahero mentions #1 doesn't apply here. and for #2, you can't set a fake Origin header on a form post, so if Origin is present and it's on your whitelist, seem like a CSRF is not possible. – Benja Jun 19 '17 at 13:17
  • 1
    #2 does apply. CORS only prevents the browser from making XHR requests. If the site changes the location URL (e.g. a native form POST or a link for a GET) then CORS does not apply. – Pace Aug 31 '17 at 15:57
  • @pace we're saying the same thing. I wrote "CORS is only for JS request" and you wrote "CORS only prevents ... XHR requests". – aleemb Oct 10 '17 at 06:44
  • 1
    Yes, sorry. I could have been more clear. I was disputing @Benja’s claim in the above comment. I agree with your answer @aleemb – Pace Oct 10 '17 at 10:46
  • 1
    I see, you're right the request would still be sent. but what I meant is that if you whitelist using the Origin header, then those cases (form submit or navigate) would be stopped, as they don't send an Origin header, which is a much simpler check than implementing XSRF tokens. – Benja Oct 21 '17 at 21:55
  • 1
    to elucidate @ineedahero answer, CSRF attack requires a user to be logged onto good.com. And that only happens on a browser. – Khanna111 May 27 '21 at 08:58
  • *CORS is only for JS request*. That statement is incorrect/imprecise. You can send some cross-origin requests using `fetch` without triggering CORS preflight; see https://twitter.com/jub0bs/status/1432025056234835980 – jub0bs Jun 06 '22 at 16:21
14

No.

The Same Origin Policy (which CORS allows you to punch selective holes through) prevents third party sites from masquerading as a user in order to read (private) data from another site.

A Cross Site Request Forgery attack is when a third party site masquerades as a user to submit data to another site (as that user). It doesn't need to read the response back.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • But it could, right? CSRF-get's for instance * to get a check photo from a vulnerable bank site, without generating origin headers or preflighted requests. [...] The photos will be displayed, and the attackers can get the photo data using Javascript and send them back.* [source](http://lenxwei.blogspot.com/), – Evan Carroll Apr 14 '15 at 18:11
  • Your assumption that CSRF attacks are limited to "submitted" data seems to be wrong. And, further, that CSRF couldn't remedy this situation is also wrong (though ymmv with even modern browsers), *If the browser checks the Access-Control-Allow-Origin header in the response and refuses to display it, it will be an effective defense.* (same source) – Evan Carroll Apr 14 '15 at 18:13
  • 1
    @EvanCarroll — In response to your first comment: Using an image like that can trigger a CSRF attack. CORS can't prevent that for the reasons described in this answer. The attacker can display the image to the user (which might be useful in phishing attacks) but they cannot make the browser send a copy of the image (or data extracted from the image) to the attacker (because the Same Origin Policy prevents it). Your source is wrong. – Quentin Apr 15 '15 at 08:38
  • @EvanCarroll — In response to your second comment: Data submitted to a server by embedding it in a query string of a URL that is loaded via an image tag is still submitted. "If the browser checks the Access-Control-Allow-Origin header" — No browser does that, so it isn't relevant in a discussion about authoring websites. "it will be an effective defense" — The Same Origin Policy is already an effective defence against other sites finding out information about what images a user has access to on a server. – Quentin Apr 15 '15 at 08:40
  • Nice answer, but I think 'Same site policy' has more things to do other than 'just preventing masqueraded Read'. It also prevents PUT and DELETE verbs. – Mohammad Reza Sadreddini Apr 07 '20 at 21:20
10

No!

CORS enables sharing between two domains where XSRF is attacking method that does not depend on CORS in anyway.

I don't understand what you mean by "CORS is properly setup" but when attacking with XSRF, browser don't ask for CORS headers on server.

CORS is not security :)

confiq
  • 2,795
  • 1
  • 26
  • 43
  • 4
    It should be put up in big bold letters: "CORS is not security!" CORS only specifies what types of cross-origin requests are allowed to your server. It shouldn't be a substitute for good security practices. – monsur Nov 05 '13 at 16:30
  • 1
    Ha thanks! I was actually speaking generally, your answer was great. But thanks for updating anyway :) – monsur Nov 06 '13 at 19:02
  • 1
    I guess what I'm trying to get at is can anyone spoof an origin header? If so wouldn't CORS or the Same-Origin-Policy break down? – programmerdave Nov 07 '13 at 14:39
  • @programmerdave A hacked or compromised browser could lead to that situation. The philosophy behind CORS relies on the user's browser being trusted. – Pace Aug 31 '17 at 16:01
  • 15
    answer doesnt say why or how, XSRF/CSRF is to make a illegitimate request on user behalf. `siteA` calling `siteB/logout` for example. Strict CORS policy prevents cross site JS calls, so how come. – Muhammad Umer Oct 19 '17 at 06:35
7

Maybe

Man this is a tough one, and it's far more complex than the others have provided for. So "maybe"

First, CORS is intended to "relax" same-origin-policy which is a default that prevents a specific type of CSRF attack. But, same-origin doesn't apply on all kinds of requests.

So the longer the session needs to time out and the more the user surfs around untrusted sites, the higher the risk is to pop onto one with a CSRF attack on it. Any tag which fires a request to an external resource can be used to perform a hidden CSRF attack – including images, link tags, some meta tags, embed and object tags and so on. Same goes for attributes which load background images or similar. You can even check if you site has been validated by someone if you replace the DTD file in the very header of the applications markup with a resource on your servers – that’s CSRF too. source

For an example of that, check this..

<img src=victim.bank/check.png?account=...>; to get a check photo from a vulnerable bank site, without generating origin headers or preflighted requests. [...] The photos will be displayed, and the attackers can get the photo data using Javascript and send them back. source

However, at least one source suggests that perhaps in the future web servers will return images with Access-Control-Allow-Origin (CORS) headers on images that will stop browsers from rendering the image. This will prevent CSRF-GET attacks of this sort..

If the browser checks the Access-Control-Allow-Origin header in the response and refuses to display it, it will be an effective defense. source

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
  • 1
    "the attackers can get the photo data using Javascript and send them back" — That is not true – Quentin Apr 15 '15 at 08:41
  • 4
    When I [run that code](http://jsbin.com/rotonagaka/1/edit?html,output), after replacing the URL with an image on a different origin, the browser console says: `Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.` So, no, it isn't possible because the Same Origin Policy kicks in. – Quentin Apr 15 '15 at 17:55
  • 3
    @Quentin Look at your network tab, it didn't prevent the request from being made, it only prevented you from accessing the data, but wouldn't prevent a modification from occurring if the request modified data. This should still be safeish since a GET request shouldn't modify data. – Pace Aug 31 '17 at 16:34
4

Proper CORS Setup

The modern browsers try to prevent the Cross-origin request forgery attack with a security mechanism aka SOP (Same Origin Policy).

The CORS settings is going to open some restrictions of the SOP and relaxing that.

I would Interpret The Proper CORS Setup to having:

  • a browser with SOP feature
  • allow cors headers to not be * or <request-origin-host> (just being the hosts which are trusted)

SOP Restrictions

if any page requests for cross-origins, there are 3 policies:

  1. write-request like: link, redirects, xhr, form submitions (allow) (Rule 1)
  2. embeding-request like: <script>, <link>, <img>, <video>, <audio>, <object>, <embed>, @font-face, <iframe> (allow) (Rule 2)
  3. read requests (disallow) (Rule 3)

Among the above the first option (write-request) are subject to abuse for cross site request forgery.

The SOP mechanism just ALLOWED these write requests

Why?

  • for backward compatibility with the existing websites
  • convenient development & usage (just think if there exists a complex solution for a redirection what would happened!!! )

The only help that the Browser SOP does for this step is to send a pre-flight request for the resource-changing (POST/PUT/...) XHR requests

note: in future steps it will helps more than this

in the pre-flight request, the server sends the CORS Allow Header and browser finds out that if the resource changing request is allowed or not.

for example: if there is a form with post method which change a resource on server, the CORS Allowance Header will get received from server, but resource on server already has been changed. (antidote after sohrab's death )

SOP will prevent CSRF attack on xhr requests & not the application/x-www-form-urlencoded requests

  • there can be a form on evil.example or an script can append a form in DOM and automatically sending that.

or the xhr preflight it self may not prevent as we expected because:

  • in some browser it can be disabled because of performance (not having 2 requests)
  • if Origin header not set
  • Server may allow *
  • some bugs on preflight request expose the functionalities ...

CSRF-Token Mechanism

CSRF token can be used on both form and xhr requests.

CSRF-token mechanism prevents the CSRF attack if only if CSRF Token not exposed to cross-origin malicious scripts

but this scenario can be imaginable that: an script on malicious website:

  • first request for the form (aka edit form or delete form) & get the token
  • then send the token with application/x-www-form-urlencoded or xhr

SOP Supports CSRF-token

I have mentioned that SOP Restricts The Read request. and only allowed the read requests which are embeded.

so SOP will prevent the CSRF-token to get exposed by an malicious script (getting the form & creating a fake form with the token) if:

  • Proper CORS Setup
  • the form cannot get embedded

TL;DR

The SOP mechanism (with Rule #1) (Proper CORS setup) can prevent only CSRF xhr (can have some flaws in implementations) (canot protect all scenarios)

The CSRF-Token can protect CSRF Attack if the token hasn't get compromised

The SOP mechanism (with Rule #3) can protect CSRF-token & CSRF-token protect users from CSRF-attack

We should make attention to not compromise the CSRF-token with embedded resource Rule (Rule #2). (mostly iframe abuse)

MDN How to block cross-origin access

  • To prevent cross-origin writes, check an unguessable token in the request — known as a Cross-Site Request Forgery (CSRF) token. You must prevent cross-origin reads of pages that require this token.
  • To prevent cross-origin reads of a resource, ensure that it is not embeddable. It is often necessary to prevent embedding because embedding a resource always leaks some information about it.
  • To prevent cross-origin embeds, ensure that your resource cannot be interpreted as one of the embeddable formats listed above. Browsers may not respect the Content-Type header. For example, if you point a
tag at an HTML document, the browser will try to parse the HTML as JavaScript. When your resource is not an entry point to your site, you can also use a CSRF token to prevent embedding.

Further Readings

Same Origin Policy

CSRF Token mechanisms (implementation in The Laravel)

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Abilogos
  • 4,777
  • 2
  • 19
  • 39
-4

Actually CORS does contribute to security. CORS helps a lot in relation to XSS and CSRF attacks between different hosts. If a website has an XSS vulnerability and the attacker wants to use it to send a malicious request to another webpage through xmlhttprequest, thanks to CORS he is not going to be able to.

OGHaza
  • 4,795
  • 7
  • 23
  • 29
  • 1
    CORS doesn't provide any additional security here. Before the CORS spec, the same xhr initiated request would have been rejected outright by the browser. – Ray Nicholus May 19 '14 at 20:50