60

I've been reading in the last couple of days about CORS and in a lot of places it's mentioned as it is a "Security" feature to help the world from cross domain forgery.

I still don't see the benefit and the reasoning for CORS. Ok, browsers will do a preflight request / server will validate the origin. But an attacker can easily create an HttpRequest top-bottom with whatever Headers(Origin) he wants and he will get access to the resource.

How is CORS helping and what's the benefit of it?

Anders
  • 64,406
  • 24
  • 178
  • 215
Dan Dinu
  • 709
  • 1
  • 6
  • 5

6 Answers6

76

I'll start my answer by saying that many people misunderstand the Same Origin Policy and what CORS brings to the table.

Some of the up-voted answers already here are stating that the Same Origin Policy prevents cross-site requests, and therefore prevents CSRF. This is not the case. All the SOP does is prevent the response from being read by another domain (aka origin). This is irrelevant to whether a "classic" CSRF attack is successful or not.

By "classic" I'm referring to the types of request that were possible before CORS came about. That is, the types of request that can be sent via HTML forms as well as XHR (e.g. GET or POST without custom headers).

The only time the SOP comes into play with "classic" CSRF is to prevent any token from being read by a different domain.

Of course, now we have CORS and all sorts of cross-domain requests are possible such as PUT and DELETE, CORS does in fact protect against these by requiring a pre-flight. However, generally speaking CORS is not providing greater net benefit because the reason this functionality is available in the first place is due to CORS.

All CORS does is relax the SOP when it is active. It does not increase security (except perhaps allowing cross-domain resource sharing to be standardised and prevent developers from introducing flaws with something like JSONP), it simply allows some exceptions to take place. Some browsers with partial CORS support allow cross site XHR requests (e.g. IE 10 and earlier), however they do not allow custom headers to be appended. In CORS supported browsers the Origin header cannot be set, preventing an attacker from spoofing this.

I mentioned domains were different origins. Origins can also differ by port and protocol when talking about AJAX requests (not so much with cookies).

Finally, all of the above has nothing to do with forged requests coming directly from an attacker, for example with curl. Remember, the attacker needs to use the victim's browser for their attack. They need the browser to automatically send its cookies. This cannot be achieved by a direct curl request as this would only be authenticating the attacker in this type of attack scenario (the category known as "client-side attacks").

The benefit of CORS is that it allows your domain to allow reads from another trusted domain. So if you have http://data.example.org you can set response headers to allow http://site.example.com to make AJAX requests and retrieve data from your API.

SilverlightFox
  • 33,408
  • 6
  • 67
  • 178
  • 5
    This is the most correct answer. Also nobody seems to be mentioning that most modern CORS libraries let you whitelist what Origins you want to allow. Everything I read seems to assume you should just be allowing all Origins which usually is not the case for most people. – Alex Urcioli Mar 06 '16 at 20:30
  • 1
    All the SOP does is NOT prevent the response from being read by another domain! It doesn't even allow browsers to send a preflighted request to another domain. – Daniel B Mar 07 '18 at 07:32
  • @Daniel What kinds of requests are blocked by the SOP? – curiousguy Jun 25 '18 at 07:58
  • I have some thoughts regarding POST requests without custom headers and with a standard `Content-Type` header value (e.g. `application/x-www-form-urlencoded`). For this requests, the browser (at least, Chrome) following the `CORS` policy WILL NOT make a preflight OPTIONS request and will send the `POST` request right away. This means that if a user visits the site of an attacker and this malicious site makes this POST request via AJAX with the `withCredentials` options set to true (thus, sending session cookies), then CSRF would be successful. Am I right? – user3019105 May 04 '19 at 16:09
  • @ton Yes, you are correct for all (?) modern browsers. See my post here: https://markitzeroday.com/x-requested-with/cors/2017/06/29/csrf-mitigation-for-ajax-requests.html It has some examples, and shows mitigation by checking for a custom header. – SilverlightFox May 04 '19 at 21:59
  • I know this answer is a few years old now, but there are browser extensions which can spoof the origin header. I've never tested it but one would think it's possible an attacker can leverage the victim's browser's extension. Maybe the user left the Origin header set and forgot to remove the value or disengage the extension. Or, the attacker might be able to directly enter a value to the extension. I'm just thinking out loud here. – user3621633 May 31 '19 at 15:03
  • @user3621633 if the attacker were able to set a value in that extension, then the attacker would already have access to the victim's computer, in which case he'd have access to the cookies, which means he'd have no need to spoof the origin header. He'd just grab the cookies and leave. – David Klempfner Dec 13 '20 at 04:44
  • "All the SOP does is prevent the response from being read by another domain (aka origin)". This isn't entirely true. It also prevents the request from being sent, if that request is not a "simple" request such as PUT/DELETE or GET/POST with custom headers. – David Klempfner Dec 13 '20 at 04:46
  • @david As the question was "Is CORS helping in anyway against Cross-Site Forgery?", my answer was constructed within this context. Early browsers could only send XMLHttpRequests to the same domain, therefore CSRF via XHR was not an issue. CORS was developed to allow cross-domain requests to happen, and you are right in that PUT/DELETE or GET/POST with custom headers are blocked by the Same Origin Policy unless the server's CORS configuration allows it. However, if CORS did not exist then PUT/DELETE or GET/POST with custom headers would not be possible, as HTML forms do not allow these options. – SilverlightFox Dec 13 '20 at 20:37
  • @david My point was that some of the other answers suggested that the SOP or a carefully constructed CORS configuration was a panacea for all types of CSRF and I didn't want people thinking they did not need to now protect against CSRF because CORS exists. – SilverlightFox Dec 13 '20 at 20:38
  • @Daniel Please see what I wrote [above](https://security.stackexchange.com/questions/97825/is-cors-helping-in-anyway-against-cross-site-forgery/97938?noredirect=1#comment497803_97938). – SilverlightFox Dec 13 '20 at 20:44
  • @david answer updated to clarify, thanks for your input. – SilverlightFox Dec 13 '20 at 20:55
  • @SilverlightFox *They [the attackers] need the browser to automatically send its cookies.* Cookies (or other forms of ambient authority) need not be involved. The attacker may want to exploit the victim's unauthenticated access to a server located within a private network (a.k.a. tunnelling). See https://www.youtube.com/watch?v=wgkj4ZgxI4c&t=26m30s – jub0bs Aug 27 '21 at 10:01
  • 1
    @jub0bs: True, I used "cookies" as the most common example, but it could be a different form of auth such as digest, basic, certificate based, or, as you mention by request IP address only. I answered a similar question along those lines [here](https://security.stackexchange.com/a/44058/8340) in regards to CORS . – SilverlightFox Sep 01 '21 at 11:33
16

You're mixing things up. CORS is not meant to protect your application from crafted http requests, it's meant to protect you from a certain kind of attacks that "steals" the user's cookies or access tokens, by checking what sites can access your resource.

It's mostly used to protect your server/application from cross-site request forgery, where a malicious site will do a request on behalf of the user, possibly with malicious intents (credentials change, money transfer...), exploiting the fact that the browser will send any login and session cookie still alive and valid for your site.

If CORS is correctly configured, the ajax request of the attacker's site will be rejected, as, by default, it will only accept requests by the same site.

This DOES NOT mean you should not sanitize your inputs, and only protects you from a certain type of CSFR attacks. Should the attacker get your user's cookies/access tokens he will be granted access anyway, and that's why most authentication processes should use SSL as an additional layer of protection.

PS: This assumes the browser your user is using is up to date, has no flaws and is correctly obeying the same origin policy.

EDIT: As for preflight requests, this is an additional measure to be sure the site is granted access, and are not done for all cross-origin requests

BgrWorker
  • 1,941
  • 1
  • 10
  • 17
  • This answer really cleared things up for me. Now I understand that it is the request**ed** third-party resource that needs to allow the request, not the server that generated the request**ing** page. – alexw Dec 14 '15 at 01:39
  • 7
    @Sebastiano, CORS is not meant to protect you from CSRF. (CSRF would stil be possible via ` – Pacerier Jan 23 '16 at 18:55
  • CORS is not for protection, but a resource sharing. To some extent it is just the opposite of CRSF. The former allows for cross-origin requests, the latter forbids (or prevent some malicious) cross-origin requests. Also CORS request is generally not rejected by the server, but the response from the server "rejected" by the client, i.e. the browser. So SOP does not necessarily prevent CRSF, as clarified in @SilverlightFox's answer. – wlnirvana Feb 20 '20 at 07:57
  • 1
    @alexw please don't get confused by this answer. It's not correct. CORS makes your application LESS secure. Any of the security benefits this answer talks about, are actually already there by default because of the Same-Origin Policy. See my blog for a good explanation: https://levelup.gitconnected.com/simulating-a-csrf-attack-part-1-5ec8b0f8b152 – David Klempfner Dec 13 '20 at 04:50
3

Does it make sense to summarise all this as follows:

  • SOP (Single Origin Policy) ensures CSRF attacks can't be made from within a modern, up to date, browser due to the fact that the attacker would have to be POSTing from another domain.

  • CSRF (Cross-Site Request Forgery) tokens ensure that dangerous POST requests can't be made outside of the browser (where SOP doesn't apply, e.g. using curl), because they have no access to authentication data in user cookies outside of a shared browser experience.

  • CORS (Cross-Origin Resource Sharing) can be used to relax restrictions on SOP to browsers, but only if the resource server allows it through CORS headers. Therefore it has the potential to actually weaken security if used incorrectly.

Grub
  • 131
  • 1
  • 1
    Your first point is not accurate. CSRF attacks can be made because for simple GET/POST requests, all SOP does is stop the browser being able to read the response, the request still gets sent. The rest sounds ok. – David Klempfner Dec 13 '20 at 04:54
  • Second point also seems not accurate. CSRF attacks happen _within_ the browser, because the browser will automatically send the session cookie to the trusted site. Requiring an additional CSRF token ensures the request cannot be forged. When using `curl`, you need to provide the session cookie yourself (that you don't have), so an attacker cannot make a successful request regardless. – henk Jan 14 '22 at 10:29
3

I've been reading in the last couple of days about CORS and in a lot of places it's mentioned as it is a "Security" feature to help the world from cross domain forgery.

You either misunderstood the benifits of CORS or may be you have read that in some amateur blogs done by developers who are more worried about how to make it work than how to make it safe (if you understand what I mean), because CORS rather makes your web application vulnerable to such attacks (CSRF) when you open cross-origin requests from the attacker's origin by using CORS with the following header: Access-Control-Allow-Origin: *

How is CORS helping and what's the benefit of it?

CORS was born to lighten the restrictions of the SOP for trusted requests only. But the problems start exactly with that trust. An attacker could do harm through the origins by forging malicious requests through GET and POST methods for example, and may expose you even DNS rebinding

  • 4
    What is the relevance of DNS rebinding in the context of CORS? If a DNS rebinding attack is successfully being carried out, then information is already being leaked (regardless of CORS headers). If CORS is incorrectly set up, then information can already be accessed without DNS rebinding. In either case, I don't understand why DNS rebinding deserved to be mentioned in your answer. Did I overlook anything? – Rob W Aug 26 '15 at 16:02
  • @RobW If you implement CORS *as it is*, I mean without making the necessary to check the origin and host headers have the same host name then you are vulnerable to DNS rebinding. –  Aug 26 '15 at 17:14
  • 2
    If you always reply with `Access-Control-Allow-Origin: *`, then the resource is already public, so DNS rebinding doesn't add any value. Could you give an example (requests & responses) where DNS rebinding and CORS together result in a security issue, which really requires both components in the attack? – Rob W Aug 26 '15 at 17:18
  • @RobW what a resource author check when implementing CORS? By instinct he is likely (and we speak about developers) the origin header only. The origin headers displays from where the cross-origin request comes from, a developer forgets to check the host header, there comes the problem. If you want a proof of concept you may ask that in a different post (in order not to lead my answer off-topic: i mentioned that as an additional information to the OP, he asked only about CSRF) –  Aug 26 '15 at 17:26
  • 5
    By the way your answer is phrased, DNS rebinding sounds like a serious vulnerability that is highly relevant to CORS, and somehow relevant to CSRF. In order to carry out an attack that abuses origin whitelists, the attacker has to control one of those origins. DNS rebinding is not going to help over there. If the attacker controls the origin, then the only thing where DNS rebinding could be used is to steal cookies that were set after a CORS-enabled request with credentials via an attacker-controlled host name. That attack sounds a bit far-fetched. Did you have anything else in mind? – Rob W Aug 26 '15 at 18:01
2

As for this part,

browsers will do a preflight request / server will validate the origin. But an attacker can easily create an HttpRequest top-bottom with whatever Headers(Origin) he wants and he will get access to the resource.

From https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Additionally, for HTTP request methods that can cause side-effects on user data (in particular, for HTTP methods other than GET, or for POST usage with certain MIME types), the specification mandates that browsers "preflight" the request, soliciting supported methods from the server with an HTTP OPTIONS request method, and then, upon "approval" from the server, sending the actual request with the actual HTTP request method. Servers can also notify clients whether "credentials" (including Cookies and HTTP Authentication data) should be sent with requests.

As much as i am aware, if you use HTTP methods like 'PUT' instead of 'POST' and because making a cross-domain request using 'PUT' as the specified method will always be preceded by a pre-flight request checking to see if the Origin is allowed, this can prevent attacks in certain situations. This is because the origin can't be spoofed by the attacker as modern browsers don't allow client side scripting languages such as Javascript to set the 'Origin' or any custom headers cross-domain, the attack will fail.

Hope that helped.

racec0ndition
  • 581
  • 4
  • 10
  • It seems CORS helps protect against CSRF only comparing services with misconfigured CORS to services with properly configured CORS. As for services that do not interpret the Origin request header, do not respond to OPTIONS and do not include CORS headers, both old and modern browsers will stop malicious scripts from sending PUT requests against such: https://w3c.github.io/webappsec-cors-for-developers/#cors – eel ghEEz Jul 12 '17 at 15:38
  • 2
    *"non-standard HTTP methods like 'PUT'"* what? [PUT is certainly standard.](https://www.w3.org/Protocols/HTTP/1.0/spec.html#PUT) – Evan Carroll Sep 20 '18 at 18:24
  • @EvanCarroll replace "non-standard" with "not simple". PUT cannot be sent via the user's interaction with a browser. Only GET requests (user clicks on a hyperlink, or types something into the URL textbox), and POST requests (user clicks the submit button on a form). PUT/DELETE can only be sent via Javascript, which can execute in the background without the user/victim knowing about it. For more info, read "Why is PUT/DELETE treated differently to GET/POST?" section in https://medium.com/swlh/simulating-a-csrf-attack-part-2-bf6f378da625 – David Klempfner Dec 13 '20 at 05:02
1

Yes, it is helping, but not really by design.

CORS stands for Cross-Origin Resource-Sharing. It's not really intended for security. CORS is folded into the fetch API, so it's only useful for Javascript (more on that later). By default, fetch() can't grab what's not in the same origin because of the Single Origin Policy (SOP). CORS loosens that up by saying what other origins are allowed to access a resource. Also, XMLHttpRequest behaves the same way.

So, yes it can help block cross-site scripting (XSS) because the resource is trying to be accessed from across another origin. And technically, your server isn't blocking the request. It's browser that doesn't let the request go through by respecting the Access-Control-Allow-Origin header.

But that's only for Javascript. Browsers don't use CORS for Simple Requests.

That means simple GET requests (like fake images) don't get stopped by CORS. Also, POST requests not done in Javascript (ie: forms) don't trigger CORS. You still need protection against that. Security is only as strong as your weakest link, and once your start preventing CSRF at a server-level from Simple Requests, you'll realize that your CORS is just an extra layer that isn't truly necessary, but still nice to have.

ShortFuse
  • 111
  • 1
  • 1
    "Yes, it is helping". No, it's not. For something to "help", it needs to provide more value than what is already available. By default, the Same-Origin Policy is used, and CORS adds no extra security to what is already there, at all. In fact, it makes things less secure by giving you the ability to allow other domains to make requests to your domain. "So, yes it can help block cross-site scripting (XSS)", again, no it can't, because by default, browsers do this anyway because of SOP. "Browsers don't use CORS for Simple Requests", replace 'CORS' with 'pre-flight requests'. – David Klempfner Dec 13 '20 at 05:06