88

After reading about CORS (Cross-Origin Resource Sharing), I don't understand how it improves security. Cross-Domain AJAX communication is allowed if the correct ORIGIN header is sent. As an example, if I send

ORIGIN: http://example.com

The server checks if this domain is in the white list and, if it is, header:

Access-Control-Allow-Origin: [received url here]

is sent back, together with the response (This is the simple case, there are also prefighted requests, but the question is the same).

Is this really secure? If someone wants to receive the information, faking an ORIGIN headers seems like a really trivial task. Also the standard says that the policy is enforced in the browser, blocking the response if Access-Control-Allow-Origin is not correct. Obviously if anyone is trying to get that info, he will not use a standard browser to block it.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Gibarian2001
  • 907
  • 1
  • 7
  • 5
  • Read this answer is someone is unclear on what same-origin policy and CORS are and why they exist : https://stackoverflow.com/a/27294846/3340994 – nishantbhardwaj2002 Mar 08 '18 at 02:40

6 Answers6

161

The purpose is to prevent this -

  • You go to website X
  • The author of website X has written an evil script which gets sent to your browser
  • that script running on your browser logs onto your bank website and does evil stuff and because it's running as you in your browser it has permission to do so.

The ideas is that your bank's website needs some way to tell your browser if scripts on website X should be trusted to access pages at your bank.

jcoder
  • 29,554
  • 19
  • 87
  • 130
  • 9
    Your answer was very clear too, thanks. I coudn't upvote because it requires 15 reputation. – Gibarian2001 Jan 31 '11 at 17:23
  • So, CORS is not protecting the integrity of a the app on the website X it's protecting the integrity of the BANK that says that web X is to be trusted to make the API calls to the BANK? – luigi7up Dec 17 '14 at 10:12
  • 9
    @luigi7up: No, CORS does not protect anything, in fact it "weakens" security by defining exceptions to SOP. The `Access-Control-Allow-Origin` header specifies which origins (specified in the `Origin` header) are allowed to access the resource. Normally only requests with the same origin would be allowed to do so. The most important part here is: the allowing/denying is enforced by the BROWSER, not the server. This means that the `Access-Control-Allow-Origin` protects your browser, not the resource on the server or the server itself. – daniel f. Jul 29 '16 at 10:54
  • What prevents the author of website X to log you into the bank through his sites backend which would then be used as a proxy? It's just an additional layer he would have to create, but it would completely circumvent the CORS issue he would have in the browser I guess.. So this seems like a browser-only protection which seems pretty meaningless to me if you can go around it in a very simple way.. – tkit Mar 06 '17 at 09:46
  • 1
    @pootzko: in your scenario the malicious website X would not have a valid session for the banking website. Even if the victim is logged in in his banking (for example in another tab), the malicious site X would not have access to that session, because of the cookie policy enforced by the browser: the browser would never send the session cookie of the bank to website X. – daniel f. May 09 '17 at 10:53
77

Just to add on @jcoder 's answer, the whole point of the Origin header isn’t to protect the resources requested on a server. That task is up to the server itself via other means exactly because an attacker is indeed able to spoof this header with the appropriate tools.

The point of the Origin header is to protect the user. The scenario is the following:

  • an attacker creates a malicious website M

  • a user Alice is tricked to connect to M, which contains a script that tries to perform some actions through CORS on a server B that actually supports CORS

  • B will probably not have M in its Access-Control-Allow-Origin header, cause why would it?

  • The pivotal point is that M has no means to spoof or overwrite the Origin header, because the requests are initiated by Alice's browser. So her browser will set the (correct) Origin to M, which is not in the Access-Control-Allow-Origin of B, therefore the request will fail.

Alice could alter the Origin header herself, but why would she, since it would mean she is harming herself?

TL;DR: The Origin header protects the innocent user. It does not secure resources on a server. It is spoofable by an attacker on his own machine, but it cannot be spoofed on a machine not under his control.

Servers should still protect their resources, as a matching Origin header doesn't mean an authorized access. However, a Origin header that does NOT match means an unauthorized access.

daniel f.
  • 1,421
  • 1
  • 13
  • 24
  • 15
    Very nice answer. The best one overall IMHO. – petersaints Jul 29 '16 at 01:02
  • 1
    Why was this not the chosen answer? This is clearly the best. The fourth point mentioned in this answer is what the poster is really asking for. – alaboudi May 04 '17 at 19:23
  • 1
    best answer Daniel. This is the whole point of CORS: "The pivotal point is, that M has no means to spoof or overwrite the Origin header, cause the requests are initiated by ALICE's browser. So her browser will set the (correct) Origin to M, which is not in the Access-Control-Allow-Origin of B, therefore the request will fail." – Lukas Lukac Jul 31 '18 at 16:35
58

You can't fake an Origin header with JavaScript in a web browser. CORS is designed to prevent that.

Outside of a web browser, it doesn't matter. It isn't designed to stop people from getting data that is available to the public. You can't expose it to the public without members of the public getting it.

It is designed so that given:

  • Alice, a person providing an API designed to be accessed via Ajax
  • Bob, a person with a web browser
  • Charlie, a third party running their own website

If Bob visits Charlie's website, then Charlie cannot send JS to Bob's browser so that it fetches data from Alice's website and sends it to Charlie.

The above situation becomes more important if Bob has a user account on Alice's website which allows him to do things like post comments, delete data, or see data that is not available to the general public — since without protection, Charlie's JS could tell Bob's browser to do that behind Bob's back (and then send the results to Charlie).

If you want to stop unauthorized people from seeing the data, then you need to protect it with passwords, SSL client certs or some other means of identity-based authentication/authorization.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • 1
    Basically CORS or Cross-Origin Resource Sharing and authorization are two separate things. As the acronym suggests it's actually to ALLOW cross origin sharing. Whether a client is ACTUALLY allowed to do this is for your authorization logic to determine. – reaper_unique May 07 '16 at 20:47
15

The purpose of the same origin policy isn't to stop people from accessing website content generally; if somebody wants to do that, they don't even need a browser. The point is to stop client scripts accessing content on another domain without the necessary access rights. See the Wikipedia entry for Same Origin Policy.

Andy E
  • 338,112
  • 86
  • 474
  • 445
  • 2
    "The point is to stop client scripts accessing content on another domain" this was solved with the Same Origin Policy. No? I mean my website sends you some JS and your browser won't allow ajax calls to some other domain. that's the same origin policy. CORS is doing the very oposit - allows my ajax to access the other domain. I am missing something huge here :) – luigi7up Dec 17 '14 at 10:14
  • 1
    to @luigi7up: Yes, CORS does the opposit. It lets the owner of a web site to grant access to his services from more than one trusted domain. – SergeyT Jul 02 '15 at 18:15
11

"After reading about CORS, I don't understand how it improves security."

CORS does not improve security. CORS provides a mechanism for servers to tell browsers how they should be accessed by foreign domains, and it tries to do so in a way that is consistent with the browser security model that existed before CORS (namely the Same Origin Policy).

But the Same Origin Policy and CORS have a limited scope. Specifically, the CORS specification itself has no mechanism for rejecting requests. It can use headers to tell the browser not to let a page from a foreign domain read a response. And, in the case of preflight requests, it can ask the browser not to send it certain requests from a foreign domain. But CORS doesn't specify any means for the server to reject (that is, not execute) an actual request.

Let's take an example. A user is logged in to site A via a cookie. The user loads malicious site M, which tries to submit a form that does a POST to A. What will happen? Well, with or without CORS, and with or without M being an allowed domain, the browser will send the request to A with the user's authorization cookie, and the server will execute the malicious POST as if the user initiated it.

This attack is called Cross-Site Request Forgery, and CORS itself does nothing to mitigate it. That's why CSRF protections are so important if you allow requests to change data on behalf of users.

Now, the use of the Origin header can be an important part of your CSRF protection. Indeed, checking it is part of the current recommendation for multi-pronged CSRF defense. But that use of the Origin header falls outside the CORS specification.

In sum, CORS is a useful specification for extending the existing Same Origin Policy security model to other accepted domains. It doesn't add security, and sites need the same kinds of defense mechanisms that they did before CORS.

Kevin Christopher Henry
  • 46,175
  • 7
  • 116
  • 102
2

I am late to answer but I don't think any post here really provides the sought answer. The biggest takeaway should be that the browser is the agent that is writing the origin header value. An evil script cannot write the origin header value. When the server responds back with a Access-Control-Allow-Origin header, the browser tries to ensure that this header contains the origin value sent earlier. If not, it triggers an error and does not return the value back to the requesting script. The other answers to this question present a good scenario to when you would like to deny an answer back to the evil script.

@daniel f also provides a good answer to the question

alaboudi
  • 3,187
  • 4
  • 29
  • 47