Live data from Hacker News

Developers don't understand CORS

fosterelli.co

131–140 of 366 posts

Re: Developers don't understand CORS

#131

Earlier quoted context omitted.

In a nutshell, because of CORS, one domain cannot communicate with another domain. The domain being communicated with, will automatically reject requests, unless the server is setup to specifically allow the request to go through via setting CORS headers to white list specific domains or all domains (bad idea).

So, that is not my understanding, but I could definitely be wrong. So, the one domain will attempt to communicate, the other domain will receive the request and return a response. If the client doesn’t ‘like’ the response, it will error.

This only holds for indempotent requests (so in practice GET). Non-indempotent requests are "preflighted" and don't happen at all when the policy does not allow them.

So in fact CORS without any server-side configuration allows one to do arbitrary GET requests with cookies and authentication through XHR, but you could always just dynamically create IMG (as in the Zoom kludge) or SCRIPT (and the response will be executed in the page context, which is huge security risk as well as how JSON-P works) tag.

In other words: if your application does something security-sensitive (ie. write to anything other than log file) as part of GET request apart from producing the response, then your application is broken and same-origin policy nor CORS has nothing to do with that.

Re: Developers don't understand CORS

#132
post #12

I certainly don't understand CORS. I've read about it several times and I don't remember what I read. It's like CORS has a teflon coating that prevents it from sticking in my mind. I know what CORS is for and why you need it, but I have no idea how, where, and when to use it.

I have some basic understanding of it. I'll try to simplify what I know if anyone else is feeling confused about CORS. - You visit evil.com. - Evil tries to makes an HTTP request to bank.com/transfer.php - But before the request goes through the Browser says, hey, wait a minute I first need to make sure if evil.com can access bank.com - Browser asks bank.com, if evil.com (also known as origin) is allowed by sending a…

No.

- You visit evil.com

- Evil tries to make an HTTP request to bank.com/transfer.php

- The browser happily performs the request, authenticated with your cookies, and the bank, having a CSRF vulnerability, happily sends your money to the attacker.

- Since 'evil.com' and 'bank.com' are different origins, Browser refuses to provide the response to evil.com, but the attacker doesn't care, he got the money.

CORS allows you to relax these restrictions, not tighten them.

Now, bank doesn't like these attacks. So they make the legitimate application send an additional custom header, "X-Totally-Secure: true". Despite being a really bad idea, if (big if) the browser follows the standards, this prevents the attack:

- evil.com tries to make the HTTP request as before

- Browser lets it through, as before

- Bank rejects the request because it's missing the magic header

So the attacker adds the header to the request:

- evil.com tries to make a non-standard HTTP request to bank.com/transfer.php, with the header attached

- BECAUSE IT'S A NON-STANDARD REQUEST, browser asks bank.com (as you described, OPTIONS)

- Bank.com replies "wtf do you want I don't know what OPTIONS is"

- Browser refuses to make the request

Unfortunately, the bank forgot that they have a marketing department, that runs ournewbankapp.com, and shows your current balance in the fake screenshot of the app to show how awesome it is. And your bosses' bosses' boss has yelled at the IT department that rolled out the security measure to make it work again. They make ournewbankapp.com send the magic header (including access-control-allow-credentials), but now the OPTIONS request fails. So they teach the web server to respond with "everyone is allowed" (with "access-control-allow-origin: *" as you described) because they're lazy and dumb.

But because browser vendors know that developers are lazy and dumb, the browser completely ignores this: If access-control-allow-credentials is set, the allowed origin must be listed explicitly. The developers give in, and explicitly add ournewbankapp.com to the header, and now it works, but the attack doesn't work.

(part 2 follows)

Re: Developers don't understand CORS

#133
post #12

I certainly don't understand CORS. I've read about it several times and I don't remember what I read. It's like CORS has a teflon coating that prevents it from sticking in my mind. I know what CORS is for and why you need it, but I have no idea how, where, and when to use it.

I was also surprised to read: "the browser explicitly ignores any CORS policy for servers running on localhost." on the Zoom vulnerability writeup.

Among all the W3 specs, the CORS one is definitely not the largest spec. See https://www.w3.org/TR/cors/

Ultimately the Zoom vulnerability reminded us that there is always a trade off between usability and security. Most of the developers default to usability and simplicity.

The average developer looks for the fastest way to achieve "what I want to do". And they do not even question installing stuff with "curl https://any.domain.com/any-script | sudo bash".

And that is the root of all evils.

Re: Developers don't understand CORS

#134
post #2

Totally agree. Something about CORS and the resources out there makes newcomers think that it's something the client has to do differently. I thought this when first doing cross-origin stuff, and thought it was just me until my dad (programmer for 30 years) got stuck on it the exact same way. Also, the author makes a good point that `Access-Control-Allow-Origin: *` is pretty dangerous. I hadn't really worried about i…

> Something about CORS and the resources out there makes newcomers think that it's something the client has to do differently

I think that "something" is the fact that the client does the blocking. Generally the servers are perfectly willing to provide the data. Heck, if you sniff the packets, you could even look at the data blocked by CORS (assuming you're working around TLS). It's especially confusing at first that tools like curl work no problem, while browser block everything.

Re: Developers don't understand CORS

#135
post #12

I certainly don't understand CORS. I've read about it several times and I don't remember what I read. It's like CORS has a teflon coating that prevents it from sticking in my mind. I know what CORS is for and why you need it, but I have no idea how, where, and when to use it.

I have some basic understanding of it. I'll try to simplify what I know if anyone else is feeling confused about CORS. - You visit evil.com. - Evil tries to makes an HTTP request to bank.com/transfer.php - But before the request goes through the Browser says, hey, wait a minute I first need to make sure if evil.com can access bank.com - Browser asks bank.com, if evil.com (also known as origin) is allowed by sending a…

This context was incredibly useful; thank you.

Am I missing something or is this transaction actually a browser being the deciding factor for whether or not the request gets sent?

If that’s true, couldn’t a nefarious browser decide when to push a request and completely ignore the OPTIONS header?

Re: Developers don't understand CORS

#136
post #135

Earlier quoted context omitted.

I have some basic understanding of it. I'll try to simplify what I know if anyone else is feeling confused about CORS. - You visit evil.com. - Evil tries to makes an HTTP request to bank.com/transfer.php - But before the request goes through the Browser says, hey, wait a minute I first need to make sure if evil.com can access bank.com - Browser asks bank.com, if evil.com (also known as origin) is allowed by sending a…

This context was incredibly useful; thank you. Am I missing something or is this transaction actually a browser being the deciding factor for whether or not the request gets sent? If that’s true, couldn’t a nefarious browser decide when to push a request and completely ignore the OPTIONS header?

You're correct, the browser is the safety net when it comes to CORS.

Re: Developers don't understand CORS

#137

Earlier quoted context omitted.

I have some basic understanding of it. I'll try to simplify what I know if anyone else is feeling confused about CORS. - You visit evil.com. - Evil tries to makes an HTTP request to bank.com/transfer.php - But before the request goes through the Browser says, hey, wait a minute I first need to make sure if evil.com can access bank.com - Browser asks bank.com, if evil.com (also known as origin) is allowed by sending a…

Thanks for this; it helped me. Very naively, I don't understand why evil.com origin was allowed to make any request to other domains using any cookies/session/identity of the browser/user in the first place. Why was this accepted standard? I was blown away when I first learned that a request made to xyz.com while in a browser tab showing abc.com would actually complete the request using my identity on xyz.com.

By default, under the same origin policy, a browser won't allow requests cross origin.

But there are valid situations where you want a request from 1 domain to be made to other domains. This is where CORS comes in.

CORS is a mechanism to loosen security, not increase it. It allows a server to say, these are the domains (outside my own domain) who can make requests. CORS headers should be set carefully so that you are only allowing the domains that should be allowed through.

Re: Developers don't understand CORS

#138

Earlier quoted context omitted.

I have some basic understanding of it. I'll try to simplify what I know if anyone else is feeling confused about CORS. - You visit evil.com. - Evil tries to makes an HTTP request to bank.com/transfer.php - But before the request goes through the Browser says, hey, wait a minute I first need to make sure if evil.com can access bank.com - Browser asks bank.com, if evil.com (also known as origin) is allowed by sending a…

Thanks for this; it helped me. Very naively, I don't understand why evil.com origin was allowed to make any request to other domains using any cookies/session/identity of the browser/user in the first place. Why was this accepted standard? I was blown away when I first learned that a request made to xyz.com while in a browser tab showing abc.com would actually complete the request using my identity on xyz.com.

Because you used to be able to host your web site on www.compsci.tech.youruniversity.edu, and put a HTML element in there, that would send the result to myawesomeguestbook.com.

Thus, cross-origin POST requests were allowed, and changing it was impossible without breaking the web. Likewise you can include images or iframes of other origins, allowing GET requests. However, you cannot read the responses! The JavaScript APIs just make it more convenient to make these requests, but they don't change what you can do - you still can't read the response. Not allowing it in the JS API would just make the attack more annoying (fall back to the legacy methods) and limit legit use cases.

It's important that you are not allowed to make arbitrary requests: As soon as you start using advanced features like custom headers (in other words, things you couldn't do with img tags, redirects, forms, and iframes), you run into preflight (where the browser asks the server whether the request is allowed before performing it, via OPTIONS, i.e. in a way that legacy servers will not understand and safely reject).

Re: Developers don't understand CORS

#139

Earlier quoted context omitted.

I have some basic understanding of it. I'll try to simplify what I know if anyone else is feeling confused about CORS. - You visit evil.com. - Evil tries to makes an HTTP request to bank.com/transfer.php - But before the request goes through the Browser says, hey, wait a minute I first need to make sure if evil.com can access bank.com - Browser asks bank.com, if evil.com (also known as origin) is allowed by sending a…

Thanks for this; it helped me. Very naively, I don't understand why evil.com origin was allowed to make any request to other domains using any cookies/session/identity of the browser/user in the first place. Why was this accepted standard? I was blown away when I first learned that a request made to xyz.com while in a browser tab showing abc.com would actually complete the request using my identity on xyz.com.

The alternatives are grim.

As an extreme example, if I were to stream video to your browser from my website, evil.com, I would have to either host or proxy those streams through my server. Instead, I can just point your browser to a video from youtube.com or something.

If youtube.com then decides you need to log-in (or be logged-in) to verify your age (as they do), then that is between your browser and youtube.com to negotiate -- evil.com never sees your credentials.

Re: Developers don't understand CORS

#140
I find in most discussions of CORS, developers don't understand the _threat model_ it is meant to be guarding against.

I'm not sure I do, I get confused, although I think I have in the past.

I think better docs are needed, I haven't found really good educational materials that begin with the big picture (threat model, what are we actually trying to do here, what things are we trying to guard against, what things are out of scope for CORS to try to guard against), which to me is the necessary foundation to get your head around it: Where you need it, and what you will want to make it do.

Post reply on HN