6 ms·
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 m
by superasn 7y ago
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 an "OPTIONS" request first (this is before making the actual request)
- Bank.com replies in header saying "sure, everyone is allowed" (e.g. my bank), technically by setting a HTTP "Access-Control-Allow-Origin: * " header (or just evil.com instead of * )
- Browser is happy, it makes the requests and you get the data
Of course there is more to this like the server can tell which HTTP methods evil.com can do like "POST", "GET", "PUT", etc using "Access-Control-Allow-Methods". If the browser needs to send the cookies too with the request ("Access-Control-Allow-Credentials"), etc. But that is pretty much the gist of it as I understand.
- abstractbarista 7y agoThanks 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.
- tcheard 7y agoBy 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.
- ergothus 7y ago> By default, under the same origin policy, a browser won't allow requests cross origin. Save a rather short-but-impactful list of exceptions. > CORS is a mechanism to loosen security, not increase it. Would that everyone shared your understanding. Add in these two insights to those we are enlightening: * CORS is enforced by the browser, so no, your curl command working doesn't say your service is fine * That error message in the browser about 'no-cors'? It is 99% likely that no-cors is NOT what you want, so the error message is just misleading and unhelpful ...and you'll have covered my CORS wishlist :)
- squiggleblaz 7y ago> CORS is a mechanism to loosen security, not increase it. Or we could call it CORB instead (Cross origin request blocking), and then we see it's a mechanism to tighten security. Since fundamentally, what we have is an agreement against major web browser vendors that blocks cross origin requests unless the web server authors have used CORS. I mean, how many people have encountered a problem with CORS? Almost no-one, and those that have encountered a problem with CORB and solved it by enabling a shitty CORS that opened the doors. (At least, they're fixing security holes in software that was written by devs who encountered a CORB problem and fuxed it. But all CORS problems follow a CORB problem.) If we called it by its true name, maybe it would help people understand what's happening. Names are important. If developers understand CORB, they will potentially understand CORS. But no-one can understand CORS till they've understood CORB.
- Thorrez 7y agoI think you have a bad acronym collision with Cross-Origin Read Blocking. https://fetch.spec.whatwg.org/#corb https://fetch.spec.whatwg.org/#corb
- Thorrez 7y ago> By default, under the same origin policy, a browser won't allow requests cross origin. Cross origin requests are allowed (as long as they're simple). Reading the response is what's blocked.
- tgsovlerkhgsel 7y agoBecause you used to be able to host your web site on www.compsci.tech.youruniversity.edu, and put a HTML <form> 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).
- danShumway 7y agoMy reading, feel free to correct if I'm missing something. This is a compatibility feature that can never change, and shouldn't change, because we can't break the web. But my reading is that CORS is mostly a band-aid on what was a bad security policy to begin with. The problem isn't that a browser might let a web page on a separate domain send and read any arbitrary request to another domain without permission -- with the exception of DDOS and bot attacks against servers, it's difficult to think of what risks this would actually pose to users themselves. And any native program on your computer can already send an arbitrary request to an arbitrary domain and read the data -- so there are at least few arguments that it might even be beneficial for websites to be able to do the same. The security problem is that requests are made with your current cookies regardless of what domain you're on. Ideally, browsers from the start would have isolated every domain into their own container, so that if evil.com made a GET/POST request to mybank.com, it wouldn't be authenticated as me, regardless of how the server was configured. We made it so that cookies could only be read by certain domains, but we didn't think until very recently to make it so that cookies could only be sent by certain domains. And at this point, too much infrastructure relies on this behavior for us to ever come up with a better model, so we're stuck with hacks like CSRF tokens which are dependent on websites being coded well.
- xyzzy_plugh 7y agoThe 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.
- jjeaff 7y agoA tangent, but YouTube actually does not require login to verify age on embedded videos.
- superasn 7y agoYou're welcome. Yes you still can make GET requests from evil.com to bank.com/transfer.php by setting the image src or script src or form submission though you won't be able to read the response. This is probably the reason that any url that makes changes to user data like logout.php, transfer.php, etc must be a POST request (with csrf token to protect again requests created via form submissons) Also it's still possible to bypass CORS using JSONp requests or for submisson, but for that transfer.php must support jsonp too (by setting the callback method)
- abstractbarista 7y agoWow that makes more sense too. Basically, don't implement GET in any remotely-sensitive API that actually causes changes in the remote system/service? EDIT: Why isn't there a header that web servers can give out to browsers basically saying "Don't use the cookie/session I'm giving you ever, unless you're literally on this site"? I could see this being very useful for banks or other origins where they expect no requests except from direct users.
- superasn 7y agoYes also see my comment about csrf token too. If the request changes user data it must be a POST request with csrf protection. You can't make POST requests with ajax as CORS will protect you, but evil.com can create a fake form submission (with bank.com/transfer.php as the form's action) which can be a POST request. So in this case you match the csrf token which only you know and which is unique for the form/session. It's a rabbithole :)
- greenshackle2 7y agoIt seems you can make a POST request from javascript, as long as it doesn't have non-standard headers or content-type. Try it yourself: https://news.ycombinator.com/item?id=20406633 https://news.ycombinator.com/item?id=20406633
- yyyk 7y ago"Why isn't there a header that web servers can give out to browsers basically saying "Don't use the cookie/session I'm giving you ever, unless you're literally on this site"?" There is, it's relatively new though: https://blog.mozilla.org/security/2018/04/24/same-site-cookies-in-firefox-60/ https://blog.mozilla.org/security/2018/04/24/same-site-cooki...
- tgsovlerkhgsel 7y agoNo. - 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)
- superasn 7y agoIt certainly won't allow me to make xhr POST requests without sending an OPTIONS request first. Are you sure about that?
- giaour 7y agoYes, you can send some POST requests without a preflight OPTIONS request: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simpl...
- _eht 7y agoThis 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?
- philjackson 7y agoYou're correct, the browser is the safety net when it comes to CORS.
- jrochkind1 7y agoYes, and that is a very important point you noticed. Both CORS and CSP are for guarding against malicious code on the web, being executed by non-malicious standards-following browsers used by non-malicious users. (the user is in fact who is being attacked). I think is frequently confused, and it leads to a mistake in the other direction, people thinking CORS or CSP can guard against malicious user-agents operated by malicious users. It is not for that!
- minhazm 7y agoYeah that's correct, CORS is a browser feature. If you had a nefarious browser installed it could indeed defeat CORS, but at that point you already have a nefarious browser and CORS is the least of your concerns. CORS prevents a malicious site from exfiltrating/accessing data using the access you have, for example an internal site that is on your computer's network but the malicious website's servers can't directly access.
- giaour 7y agoSafari used to let you turn off CORS checks in the developer tools menu.
- tgsovlerkhgsel 7y agoOf course, anyone can use netcat to send any kind of request. However, this attack is most useful if you can get the victim's browser to send the request for you, because that way, you can get it to include the victim's authentication cookies. If you as the attacker send the request yourself, you don't have the cookies. If you make the victim's browser send it, you either can't make them use a nefarious browser, or you already won since you have code execution on the victim's machine.
- deleted 7y ago[deleted]