Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion over how Cross Origin Resource Sharing (CORS) works

From what I understand about CORS, this is how it works: I have a site foo.com which serves a page X. X wants to post data to another domain bar.com. If bar.com is CORS enabled (its headers produce Access-Control-Allow-Origin foo.com) then page X can now send data to bar.com.

As I understand to get CORS to work it's all about settingit up on bar.com, and has nothing to do with foo.com. It's all about making sure bar.com doesn't accept requests from any old domain.

However this really doesn't make sense to me. I thought CORS was designed to enable foo.com to dictate who X is allowed to communicate with. If we go back to the previous example but this time X is compromised by dodgy script so that it sends data secretly to evil.com, how is CORS going to stop that? evil.com is CORS enabled, and set to *, so it will accept requests from anything. That way a user thinking they using a site foo.com, are unwittingly sending data to evil.com.

If it is really all about bar.com protecting itself, then why does it make the browser enforce the policy?. The only conceivable situation in which this makes sense if you have evil.com serving up page Y that impersonates foo.com, that tries to send data to bar.com. But CORS is enforced by the browser, all you'd have to do is make evil.com a proxy that sends faked origin requests to bar.com (data goes from Y to evil.com, evil.com sets its fake origin to foo.com then sends it to bar.com).

It only makes sense to me if it works the other way round. foo.com is CORS enabled, and its headers are set to Access-Control-Allow-Origin bar.com. That way rouge scripts would get denied access evil.com by the browser. It then makes sense for the browser to enforce the policy because its running the scripts that could go rouge. It won't stop rouge sites from trying to send rouge data to bar.com, but bar.com can protect itself with a username/password. If foo.com has endpoints that it's expecting data back from X, then you can embed tokens into X, to ensure evil.com doesn't send data to it instead.

I feel like I'm not understanding something fundamentally important here. Would really appreciate the help.

like image 827
user1830568 Avatar asked Dec 20 '14 18:12

user1830568


People also ask

How is CORS cross-origin resource sharing possible?

CORS also relies on a mechanism by which browsers make a "preflight" request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request.

How does CORS origin work?

How CORS works. CORS allows the server to explicitly whitelist certain origin and help to bypass the same-origin policy. If your server is configured for CORS, it will return an extra header with “Access-Control-Allow-Origin” on each response.

Why is CORS a problem?

The CORS behavior, commonly termed as CORS error, is a mechanism to restrict users from accessing shared resources. This is not an error but a security measure to secure users or the website which you are accessing from a potential security breach.

How can cross-origin issues be resolved?

Cross-Origin Resource Sharing (CORS) errors occur when a server doesn't return the HTTP headers required by the CORS standard. To resolve a CORS error from an API Gateway REST API or HTTP API, you must reconfigure the API to meet the CORS standard.


2 Answers

However this really doesn't make sense to me. I thought CORS was designed to enable foo.com to dictate who X is allowed to communicate with.

No, it's about bar.com controlling use of its content.

But CORS is enforced by the browser, all you'd have to do is make evil.com a proxy that sends faked origin requests to bar.com...

Yup. And if you do, and the people at bar.com notice and care, they disallow requests from your server. You move it, they disallow the new one. Whack-a-mole time. But painful as that game of whack-a-mole is, it's a lot less painful than if the requests come directly from each individual user of foo.com, from their desktop.

Having foo.com enforce what foo.com can do doesn't make any sense. foo.com already enforces what foo.com can do, because it's foo.com that serves foo.com's content and scripts.

like image 93
T.J. Crowder Avatar answered Nov 10 '22 19:11

T.J. Crowder


It isn't about Foo.com, nor about Bar.com. It is about user.

There are two things that CORS protects against. The first is access to resources behind the firewall. The second are resources that are normally protected, unless a request is sent from a browsers with authentication or other sensitive data cookies.

CORS is a Browser technology, with support from servers, that allows foo limited freedom to call outside of its domain. It is a restricted hole punched in the restriction against cross domain scripting.

Anyone can fake the ORIGIN header and create a CORS preflight or simple request -- Of course, anyone can directly connect to the Bar server directly and make the requests without using CORS at all. Any browser can directly connect to bar.com and get data. But a modern browser will not run a script from foo.com that access a bar.com resource. People visiting websites are protected against visiting a site designed to exploit cookies or the fact that the browser is behind the corporate firewall.

So the accepted answer is WRONG. It isn't about bar.com protecting its resources -- it does this through authentication and authorization. You don't have to create a proxy to send CORS requests -- you create a proxy to strip out the CORS requests (automatically responding to the preflight request, and returning the proper headers to the browser, but sending a normal request to bar.com). But you will still need authentication to get bar.com's resources, and foo.com would still need to somehow get you to install a proxy to exploit the cross domain scripting hole that CORS protects against.

But the concluding sentence is correct -- foo.com isn't in control of the resources -- it is the browser, with a quick check with bar.com to ask it if this is something that was intended.

From the OP:

If it is really all about bar.com protecting itself, then why does it make the browser enforce the policy?. The only conceivable situation in which this makes sense if you have evil.com serving up page Y that impersonates foo.com, that tries to send data to bar.com. But CORS is enforced by the browser, all you'd have to do is make evil.com a proxy that sends faked origin requests to bar.com (data goes from Y to evil.com, evil.com sets its fake origin to foo.com then sends it to bar.com).

evil.com can already contact bar.com -- just like any human using a browser can (or curl or wget, etc). The issue is can evil.com force your browser to connect to bar.com, which may have IP filters, cookies, firewalls, etc protecting it, but javascript can connect to using your browser. So the Browser is the thing that protects the user. By disallowing cross domain scripting. But sometimes it is useful (ex: google apis, or a bank connecting to a bill paying service, etc) to cross domain script. CORS tells the browser that it is OK in this instance.

That isn't to say that there are no holes, or the the standard is the best, or that there aren't holes in implementation in the browser, or that sites are too permissive. But those are different questions...

like image 3
Gerard ONeill Avatar answered Nov 10 '22 17:11

Gerard ONeill