5 ms·
Even TFA seemingly doesn't understand CORS. Or at least misreprents it grossly: > The webserver listening in on localhost:19421 should implement a REST API and
by muvlon 4mo ago
Even TFA seemingly doesn't understand CORS. Or at least misreprents it grossly:
> The webserver listening in on localhost:19421 should implement a REST API and set a Access-Control-Allow-Origin header with the value https://zoom.us https://zoom.us. This will ensure that only Javascript running on the zoom.us domain can talk to the localhost webserver.
No, that does not do that. JavaScript from any other website can still talk to localhost:19421 just the same. CORS doesn't restrict anything, it loosens the default set of restrictions (ignoring preflight requests for now and assuming we're talking just about "safe" Methods). That Access-Control-Allow-Origin header just allows JavaScript running on zoom.us to read the responses when it queries localhost:19421. The requests happen in any case, and you must ensure in your backend that they don't cause any adverse effects.
- Lerc 4mo agoI don't think you can even say CORS does that. The degree to which CORS is poorly understood (I have read numerous (often contradictory) documentation and I don't really understand it.) means that you can't rely on it being implemented properly by an unknown party, If a protocol reaches this level of widespread confusion, I think all bets are off. Even if one end of a system performs correctly, who's to say that the other will. If people adapt their code until it works with another implementation, were they mistaken, or the other end?
- RobotToaster 4mo agoIt seems like nobody understands CORS. Including me TBH.
- Beltiras 4mo agoI don't understand it. And I'm a web developer. I don't understand the documentation, I don't understand the problem it's trying to solve and I don't understand how it's going about a solution of any problem. The closest I've come to an understanding is that it's meaningless make-work for a ledger of http calls that are not giving any security.
- bazoom42 4mo agoCORS allows JavaScript to make requests to different domains than the origin of the page. By default (without CORS), JavaScript can only communicate with the origin domain.
- embedding-shape 4mo agoBack in the day when I started web development, websites making their own requests after they loaded wasn't a thing. Eventually, XMLHttpRequest appeared, which let JS do HTTP requests at (page) runtime, and the whole "AJAX movement" kicked off. Initially, you could literally hit any website with any sort of request, so your website.com could make requests to bank.com, and the browser happily obliged. Of course, this opens up a whole host of issues, so browsers started limiting websites to just being allowed to make requests to the same Origin. But sometimes we want to be able to make requests from pages to other Origins, so CORS (Cross-Origin Resource Sharing) lets you configure your server to tell browsers that "You're allowed to make requests to me, even if you're on a different origin". This is basically the simplified version of the why and how behind CORS.
- deleted 4mo ago[deleted]
- JimDabell 4mo ago> Initially, you could literally hit any website with any sort of request, so your website.com could make requests to bank.com, and the browser happily obliged. Of course, this opens up a whole host of issues, so browsers started limiting websites to just being allowed to make requests to the same Origin. I think that’s overstating it a bit. JavaScript was introduced in Netscape 2.0 and the SOP was introduced pretty much straight away – Netscape 2.0.2 I believe. Almost 20 years passed and then CORS was created. So while it’s technically true, the timeframe in which JavaScript could make any cross-origin requests was basically the blink of an eye, and for all intents and purposes, the SOP has been around since the beginning and definitely many, many years before Ajax came around.
- 4mo ago
- xg15 4mo agoI think it still works, because the number of "client implementations" of CORS is very limited (*) - only the browsers have to implement that, and the browser devs seem to understand it well enough. So there is only one end of the system that is confused - the servers - but at least the other end - the browsers - can mostly be trusted to implement it correctly. (*) unless you're implementing an open proxy, but then you have bigger problems.
- everforward 4mo agoThere’s few implementations of the engine, but many implementations of rules for that engine. I think OPs point is that many of those rule sets probably don’t do what the author intended. I would second that, because CORS questions are common and “turn on the allow all pattern” is almost always in the top 3 suggestions. Semi-related tangent, it annoys the hell out of me that create-react-app (and the newer incarnation) don’t come with an “allow all” CORS rule. Don’t force me to figure out which arcane setting configures CORS headers, I’m the one writing the code, I’m okay with wherever the HTTP requests are going, I’ll set up real CORS headers on nginx for prod.
- spl757 4mo agoA poorly documented, poorly implememented, and poorly understood protocol is a worthless protocol. More than that, it's a potential attack surface, and the idea is to reduce those. If you are the admin of something, and you are putting things into production in which you don't fully understand the implications, because you copy/pasted some crap from stackexchange assuming the person that posted it knew what they are talking about, then you are doing it wrong. Just look at this thread. It's chaos and reinforces the fact that even people that think they know, don't really know. When in doubt, grab the RFC and figure it out.
- yallpendantools 4mo ago> When in doubt, grab the RFC and figure it out. Back in the day, I was using Cloudhopper, a Twitter-developed library for the SMPP protocol (not to be confused with SMTP!). Protocols being protocols, there are strict limits on field sizes, defined on the actual protocol spec. I noticed that Cloudhopper didn't impose those limits, however. Long story short, it turns out they just left out strictly imposing field limits because other implementations didn't care either. De facto has overruled de jura and the inmates are running the asylum!
- locknitpicker 4mo ago> A poorly documented, poorly implememented, and poorly understood protocol is a worthless protocol. The world seems to manage just well to get CORS to work, though. If developers fucking up implementations of any standard is enough justification to argue that something is worthless, you'd be hard pressed to find any software engineering topic that by your personal definition would be deemed worthless.
- SahAssar 4mo ago> assuming we're talking just about "safe" Methods That's a pretty big assumption. Any decent webdev should not let GET/HEAD/OPTIONS modify state (joining a meeting is changing state) and additionally PUT/DELETE should also be idempotent. POST with JSON (or other non-form formats) api's should also have it's content-type header checked (text/plain forms can send a JSON body but the content-type will be text/plain). PUT/PATCH/DELETE and POST with a non-form content-type (application/x-www-form-urlencoded, multipart/form-data, or text/plain) will trigger a preflight so that CORS is properly checked before the actual request reaches the server.
- bwblabs 4mo ago> Any decent webdev should not let GET/HEAD/OPTIONS modify state > additionally PUT/DELETE should also be idempotent Yes, but I think the majority of large web applications are not fully correct in terms of 'Safe and Idempotent Methods' (https://datatracker.ietf.org/doc/html/rfc9110#name-common-method-properties https://datatracker.ietf.org/doc/html/rfc9110#name-common-me...).
- rswail 4mo agoThat's because they're badly written by people that don't understand that REST doesn't mean JSON+POST+GET.
- bwblabs 4mo agoAnother quote from the article: > Further, native apps can generate a unique self-signed certificate. Just creating a certificate will not work, unless it's installed as root CA certificates in all browser trust-stores on the machine. And if the private key of the root CA is not secured correctly, one could MitM any websites. So at least you want it name constrained (https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10 https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1....), but at least in Chrome until 2023 (v112) that did not work on root CA's (https://alexsci.com/blog/name-non-constraint/ https://alexsci.com/blog/name-non-constraint/), so you had to add an intermediate CA and add the constrain there. Of course, you should also just throw away the key of the root CA. I will admit I once added basic constrains in some project with a local root CA (2020-2022), but 'incorrectly' to the root CA, and did not test it in all browsers.
- xg15 4mo ago> (ignoring preflight requests for now and assuming we're talking just about "safe" Methods) You can't ignore those because they constitute the bulk of CORS' security model. Yes, you're technically right that CORS cannot prevent other websites from making any request to your server - this would be impossible, since the browser somehow has to get the CORS headers in the first place. However what CORS absolutely lets you do is prevent requests to particular endpoints - and you can then design your API in such a way that the dangerous actions are only available behind those endpoints and thus make it safe. I.e. what's missing in the TFA quote is that the server must also change the endpoint from GET to POST (in addition to setting the CORS headers) and remove the GET endpoint. Other websites would still be able to send a GET or a preflight OPTIONS request, but they wouldn't be able to send the actual POST request. As such, Zoom's workaround had two problems: They didn't set any CORS headers, which prompted the browsers to only allow "safe", i.e. GET requests - and then put an unsafe action behind the endpoint, therefore violating the "safe" assumption. Moral of the story: Don't put actions that do something else than returning a result behind a GET request.
- z3t4 4mo agoImportantly it only prevents clients that actually cares about the cors headers. Like ohh I'm from hacker.org and the http headers says it only allows zoom.us ohh nooooo. Like it's just a http header! Now if you use a mainstream browsers and you accidentally visits hacker.org in a iframe at some shady site - then the cors header will prevent your browser from accessing it.
- paulddraper 4mo agoIt is widely assumed by users that web browsing is safe. If a browser does not implement CORS protections (but allows cross-origin requests), then its users must have non-standard expectations about security.
- Sophira 4mo agoMy understanding was that "preventing otherwise disallowed HTTP requests" was the entire point of the preflight OPTIONS request, and that CORS will do nothing if the request would otherwise be allowed. For example, a POST request with a Content-Type of "text/json" would not be allowed to be sent to third-party hosts without an OPTIONS preflight, but one with a Content-Type of "multipart/form-data" would be allowed and wouldn't be stopped by CORS at all, even to third-party hosts. (And, of course, if your endpoint just assumes JSON without strictly checking the Content-Type, then congratulations, you've just allowed any website to POST to you, with no user action required.)
- xg15 4mo ago> (And, of course, if your endpoint just assumes JSON without strictly checking the Content-Type, then congratulations, you've just allowed any website to POST to you, with no user action required.) Is that so? Neither urlencoded forms nor multipart/form-data are valid JSON on the wire, so while other websites could send requests, wouldn't they just hit a parse error?
- RagingCactus 4mo agoYou can massage a text/plain form into valid JSON. text/plain is also one of the allowed default types. It works if the server doesn't check the content-type. Source: I've done that successfully in multiple pentests. Edit: lazy LLM generated example: <form action="https://example.com/api" method="POST" enctype="text/plain"> <input name='{"key":"value", "ignore":"' value='"}'> </form> That gives you {"key":"value", "ignore":"="} The trick is to stuff the = character you cannot control into an irrelevant value.
- stymaar 4mo agoI don't understand why this is the most upvoted comment. OP is right, and you are wrong. > The requests happen in any case, and you must ensure in your backend that they don't cause any adverse effects. GET requests will be sent, but they are supposed to be idempotent so if your server is implemented in a sensible way, it cannot cause any adverse effect, and reading the response is all that matters for GET requests. For non-idempotent requests however (the only ones that are supposed to be able to have side effects), a preflight OPTION request will be sent in cross-origin context instead of sending the request itself. And unless the right headers are set in the OPTION response, the request won't be sent at all.
- Sophira 4mo agoThat's not quite correct. POST requests with certain Content-Type headers, such as text/plain or multipart/form-data, will still be allowed without any kind of preflight. If the web application doesn't check the Content-Type header strictly, then you've got a problem.
- stymaar 4mo agoYou're right, I forgot that form requests bypass the preflight.
- muvlon 4mo agoWe are saying the same things, just expressing them in different terms. Yes, only idempotent methods and "safe" POST requests don't need preflight. And I'm saying you need to make sure in your server implementation that those are actually safe. The article states that the CORS header will prevent random other websites from talking to localhost at all, which is just wrong.
- ksbd-pls-finish 4mo ago>GET requests will be sent, but they are supposed to be idempotent so if your server is implemented in a sensible way, it cannot cause any adverse effect, and reading the response is all that matters for GET requests. Just my first thought as a security engineer, but sounds like a perfect opportunity to execute a timing attack to me. For example, vheck which users exist (by measuring response time for /api/users?name=john) etc
- bazoom42 4mo ago“Can still talk to, but cant read the response” is a bit too simplied. You can’t post a json payload for example, which is how a JavaScript client would usually talk to a backend. You can only post using form data encoding, since this is already possible using a plain html form without any JavaScript. Anything beyound that, like json/xml payloads or methods other than post and get are blocked by default.
- paulddraper 4mo ago>> This will ensure that only Javascript running on the zoom.us domain can talk to the localhost webserver. > No, that does not do that. It restricts non-zoom.us domains to CORS-safe operations. Which sometimes includes making the request, sometimes includes reading the response content or headers.