What security risks exist when setting Access-Control-Allow-Origin to accept all domains?
Asked Answered
P

5

191

I recently had to set Access-Control-Allow-Origin to * in order to be able to make cross-subdomain AJAX calls. I feel like this might be a security problem. What risks am I exposing myself to if I keep the setting?

Peddle answered 17/8, 2012 at 7:6 Comment(4)
The answer https://mcmap.net/q/18430/-what-security-risks-exist-when-setting-access-control-allow-origin-to-accept-all-domains from JaffaTheCake is the correct one: “Access-Control-Allow-Origin: * is totally safe to add to any resource, unless that resource contains private data protected by something other than standard credentials… cookies, HTTP basic auth, and TLS client certificates.” And see https://mcmap.net/q/18571/-is-it-safe-to-enable-access-control-allow-origin-wildcard-for-a-public-and-readonly-webservice for more details. As long as you don’t include credentials in the request, Access-Control-Allow-Origin: * is safe. And if you do include credentials, browsers won’t allow you to do Access-Control-Allow-Origin: *. Safe.Endorsement
@Endorsement Sadly, I don't think it's that simple: security.stackexchange.com/questions/227779/…Beetle
@Endorsement I would love to chat, but it's (past) bedtime for me, here. Maybe tomorrow morning :) But yes, I was referring to the typical practice of configuring a blanket ACAO: * policy at the reverse-proxy level, which would also cover sensitive endpoints like login.Beetle
Some comments moved into chat.Endorsement
M
77

Access-Control-Allow-Origin: * is totally safe to add to any resource, unless that resource contains private data protected by something other than standard credentials. Standard credentials are cookies, HTTP basic auth, and TLS client certificates.

Eg: Data protected by cookies is safe

Imagine https://example.com/users-private-data, which may expose private data depending on the user's logged in state. This state uses a session cookie. It's safe to add Access-Control-Allow-Origin: * to this resource, as this header only allows access to the response if the request is made without cookies, and cookies are required to get the private data. As a result, no private data is leaked.

Eg: Data protected by location / ip / internal network is not safe (unfortunately common with intranets and home appliances):

Imagine https://intranet.example.com/company-private-data, which exposes private company data, but this can only be accessed if you're on the company's wifi network. It's not safe to add Access-Control-Allow-Origin: * to this resource, as it's protected using something other than standard credentials. Otherwise, a bad script could use you as a tunnel to the intranet.

Rule of thumb

Imagine what a user would see if they accessed the resource in an incognito window. If you're happy with everyone seeing this content (including the source code the browser received), it's safe to add Access-Control-Allow-Origin: *.

Mcchesney answered 5/6, 2019 at 9:22 Comment(13)
should "as it only allows requests without cookies" be "as it only allows requests with cookies"?Quadrennial
@Quadrennial no. Access-Control-Allow-Origin: * only allows requests without cookies. I've edited the answer to clarify a bit.Mcchesney
What is the difference between "*" and case without this header at all. Is it the same?Reg
I would love if "Otherwise, a bad script could use you as a tunnel to the intranet" could be further explained.Hardbitten
@Reg Then the preflight request will be failed and resource access will be blockedSelfcentered
@SamRueby say you went to my evil page, I could call fetch('https://intranet.example.com/company-private-data'), which runs on your machine, and send the results back to my server. By doing this, I've used your access to the intranet to read the intranet.Mcchesney
Surprised there's no shameless plug for youtu.be/vfAHa5GBLio?t=624Buttercup
But what if you allow any site to call your domains resources from the browser. Then super-popular-site.com decides to use your server to serve its jquery and bootstrap.css/js files. Now you have a DDOS on your site because you are allowing that. Is that considerd "safe"?Counter
@raw-binhood that's a moot point, as classic scripts don't require CORS.Mcchesney
Oh, I forgot about those “classic” scripts. My grandfather once rebuild a 74 bash script in the garage.Counter
Also, I think that in most cases you dont want your site to be loaded into an iFrame. This may allow a XFS attack (owasp.org/www-community/attacks/Cross_Frame_Scripting#). I.e attacker can steal user supplied input. While browsers are supposed to protect the iFrame from access via the original source, there have been bugs, and some tricks exist such as overlaying a div on top of the iframe.Counter
@Mcchesney What about login endpoints that are vulnerable to login CSRF? If they reply with ACAO: *, an attacker could set a up a malicious page that would send a login request with candidate credentials, read the response to determine whether the login attempt was successful and, therefore, whether the credentials are valid. They could enlist any visitor of their malicious page in a coordinated, distributed client-side credential-stuffing attack. Tim Tomes and Kevin Cody described such a browser botnet in their DerbyCon 2019 talk.Beetle
@Mcchesney That would defeat any IP-based rate limiting.Beetle
T
100

By responding with Access-Control-Allow-Origin: *, the requested resource allows sharing with every origin. This basically means that any site can send an XHR request to your site and access the server’s response which would not be the case if you hadn’t implemented this CORS response.

So any site can make a request to your site on behalf of their visitors and process its response. If you have something implemented like an authentication or authorization scheme that is based on something that is automatically provided by the browser (cookies, cookie-based sessions, etc.), the requests triggered by the third party sites will use them too.

This indeed poses a security risk, particularly if you allow resource sharing not just for selected resources but for every resource. In this context you should have a look at When is it safe to enable CORS?.

Update (2020-10-07)

Current Fetch Standard omits the credentials when credentials mode is set to include, if Access-Control-Allow-Origin is set to *.

Therefore, if you are using a cookie-based authentication, your credentials will not be sent on the request.

Therapeutic answered 17/8, 2012 at 23:54 Comment(9)
If you can give a specific example of how the shared auth access poses a security risk, I'll upvote this.Mendelssohn
@Therapeutic What about static content? (e.g. static cdn content, such as javascripts, css, static htmls etc.) Are there any security issues of setting Access-Control-Allow-Origin: * on them? There will be no nogin etc, they are public to everyone?Safier
Actually this answer is not quite correct according to the current CORS standard: "The string '*' cannot be used for a resource that supports credentials." So you cannot force a request to use transient authentication in the form of cookies, cached HTTP authentication or client SSL certificates. However if the website were for example to use local storage for authentication, that would be a problem.Ellary
@Therapeutic Well I'm not sure about the implications of Access-Control-Allow-Origin: * myself, that's why I was looking at this Q&A. I.e. I don't know what the correct answer would be, but I would be interestedEllary
@NiklasB: I tried this scenario and Chrome does follow the CORS standard as you have mentioned. i.e. the string "" is not supported with a credentials request. Here is what is reported by Chrome: "XMLHttpRequest cannot load localhost:12346/hello. A wildcard '' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'localhost:12345' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute."Award
added correction mentioned above, also put an alternative solution to wildcard for some use cases that may be coming in off search enginesTendinous
This doesn't answer the question. "This indeed poses a security risk, particularly if you allow resource sharing not just for selected resources but for every resource." What's the risk?...is what op asked.Cathodoluminescence
This is definitely a security risk blog.portswigger.net/2016/10/… and youtube.com/watch?v=wgkj4ZgxI4cPie
This doesn't answer the question. As stated above, it asks specifically what the risks are. The answer below from JaffaTheCake answers the question much more clearly.Dryclean
M
77

Access-Control-Allow-Origin: * is totally safe to add to any resource, unless that resource contains private data protected by something other than standard credentials. Standard credentials are cookies, HTTP basic auth, and TLS client certificates.

Eg: Data protected by cookies is safe

Imagine https://example.com/users-private-data, which may expose private data depending on the user's logged in state. This state uses a session cookie. It's safe to add Access-Control-Allow-Origin: * to this resource, as this header only allows access to the response if the request is made without cookies, and cookies are required to get the private data. As a result, no private data is leaked.

Eg: Data protected by location / ip / internal network is not safe (unfortunately common with intranets and home appliances):

Imagine https://intranet.example.com/company-private-data, which exposes private company data, but this can only be accessed if you're on the company's wifi network. It's not safe to add Access-Control-Allow-Origin: * to this resource, as it's protected using something other than standard credentials. Otherwise, a bad script could use you as a tunnel to the intranet.

Rule of thumb

Imagine what a user would see if they accessed the resource in an incognito window. If you're happy with everyone seeing this content (including the source code the browser received), it's safe to add Access-Control-Allow-Origin: *.

Mcchesney answered 5/6, 2019 at 9:22 Comment(13)
should "as it only allows requests without cookies" be "as it only allows requests with cookies"?Quadrennial
@Quadrennial no. Access-Control-Allow-Origin: * only allows requests without cookies. I've edited the answer to clarify a bit.Mcchesney
What is the difference between "*" and case without this header at all. Is it the same?Reg
I would love if "Otherwise, a bad script could use you as a tunnel to the intranet" could be further explained.Hardbitten
@Reg Then the preflight request will be failed and resource access will be blockedSelfcentered
@SamRueby say you went to my evil page, I could call fetch('https://intranet.example.com/company-private-data'), which runs on your machine, and send the results back to my server. By doing this, I've used your access to the intranet to read the intranet.Mcchesney
Surprised there's no shameless plug for youtu.be/vfAHa5GBLio?t=624Buttercup
But what if you allow any site to call your domains resources from the browser. Then super-popular-site.com decides to use your server to serve its jquery and bootstrap.css/js files. Now you have a DDOS on your site because you are allowing that. Is that considerd "safe"?Counter
@raw-binhood that's a moot point, as classic scripts don't require CORS.Mcchesney
Oh, I forgot about those “classic” scripts. My grandfather once rebuild a 74 bash script in the garage.Counter
Also, I think that in most cases you dont want your site to be loaded into an iFrame. This may allow a XFS attack (owasp.org/www-community/attacks/Cross_Frame_Scripting#). I.e attacker can steal user supplied input. While browsers are supposed to protect the iFrame from access via the original source, there have been bugs, and some tricks exist such as overlaying a div on top of the iframe.Counter
@Mcchesney What about login endpoints that are vulnerable to login CSRF? If they reply with ACAO: *, an attacker could set a up a malicious page that would send a login request with candidate credentials, read the response to determine whether the login attempt was successful and, therefore, whether the credentials are valid. They could enlist any visitor of their malicious page in a coordinated, distributed client-side credential-stuffing attack. Tim Tomes and Kevin Cody described such a browser botnet in their DerbyCon 2019 talk.Beetle
@Mcchesney That would defeat any IP-based rate limiting.Beetle
F
13

AFAIK, Access-Control-Allow-Origin is just a http header sent from the server to the browser. Limiting it to a specific address (or disabling it) does not make your site safer for, for example, robots. If robots want to, they can just ignore the header. The regular browsers out there (Explorer, Chrome, etc.) by default honor the header. But an application like Postman simply ignores it.

The server end doesn't actually check what the 'origin' is of the request when it returns the response. It just adds the http header. It's the browser (the client end) which sent the request that decides to read the access-control header and act upon it. Note that in the case of XHR it may use a special 'OPTIONS' request to ask for the headers first.

So, anyone with creative scripting abilities can easily ignore the whole header, whatever is set in it.

See also Possible security issues of setting Access-Control-Allow-Origin.


Now to actually answer the question

I can't help but feel that I'm putting my environment to security risks.

If anyone wants to attack you, they can easily bypass the Access-Control-Allow-Origin. But by enabling '*' you do give the attacker a few more 'attack vectors' to play with, like, using regular webbrowsers that honor that HTTP header.

Farci answered 16/10, 2013 at 23:13 Comment(11)
Look at this from the point of view of an unwary end user. Someone can set up a malicious webpage which injects JavaScript to pass data between the real site and a malicious site (let's say they want to steal your password). The end user's web browser will normally block this cross site communication, but if the Access-Control-Allow-Origin is set, then it will be allowed, and the end user will be none the wiser.Savoury
Yes, setting Access-Control-Allow-Origin * on a malicious website that hosts scripts to steal passwords is strongly discouraged :-)Farci
Oh, I got a downvote for the joke. No, I cant look at it from a user perspective. It's the webmaster, or sitebuilder, that decides to set the HTTP header. Someone can set up a malicious webpage - yes, and that someone will add the malicious directive, too. And again, any client - like an infected webbrowser - may choose to ignore http headers whatever is set in them.Farci
I keep on getting downvotes. If anyone wants to downvote this, please explain why ?Farci
@Farci You are correct in that someone could make a script to just totally ignore the header. If the data is accessible, it's accessible with or without CORS headers. There's another attack vector you're not considering though. Suppose I log into my bank's website. If I go to another page and then go back to my bank, I'm still logged in because of a cookie. Other users on the internet can hit the same URLs at my bank as I do, yet they won't be able to access my account without the cookie. If cross-origin requests are allowed, a malicious website can effectively impersonate...Khudari
@Farci ... the user. Put another way, you might just visit my site (which could even be a normal site, with nothing suspicous... maybe it's a real legit site that was just hijacked!) but some JavaScript that makes HTTP requests to your bank to transfer some funds to my account. The bank doesn't know the difference between requests from its pages or requests from other pages. Both have that cookie enabling the request to succeed.Khudari
@Farci Let me give you a more common example... one that happens all the time. Suppose you have a common home router, such as a Linksys WRT54g or something. Suppose that router allows cross-origin requests. A script on my web page could make HTTP requests to common router IP addresses (like 192.168.1.1) and reconfigure your router to allow attacks. It can even use your router directly as a DDoS node. (Most routers have test pages which allow for pings or simple HTTP server checks. These can be abused en masse.)Khudari
@Farci By not allowing cross-origin requests, you effectively put a wall up between what two different sites can access from the same browser. It prevents one site from accessing another's data, impersonating the user that may have previously logged in.Khudari
@Khudari - thanks for the thorough comments. A bank and a router are good examples of sites that really dont want cross-origin requests (allthough the cookie example wont work with Access-Control-Allow-Origin *). What the header name doesn't make clear is that its actually a client side security mechanism, which makes it sounds much stronger (or more dangerous) than it really is.Farci
@Khudari .. but "The string '*' cannot be used for a resource that supports credentials." w3.org/TR/cors/#resource-requests. A more specific Access-Control-Allow-Origin url would work.Farci
This is a non-answer. Op asks what the security implications of enabling CORS for all domains are. This answer provides none.Cathodoluminescence
T
11

Here are 2 examples posted as comments, when a wildcard is really problematic:

Suppose I log into my bank's website. If I go to another page and then go back to my bank, I'm still logged in because of a cookie. Other users on the internet can hit the same URLs at my bank as I do, yet they won't be able to access my account without the cookie. If cross-origin requests are allowed, a malicious website can effectively impersonate the user.

Brad

Suppose you have a common home router, such as a Linksys WRT54g or something. Suppose that router allows cross-origin requests. A script on my web page could make HTTP requests to common router IP addresses (like 192.168.1.1) and reconfigure your router to allow attacks. It can even use your router directly as a DDoS node. (Most routers have test pages which allow for pings or simple HTTP server checks. These can be abused en masse.)

Brad

I feel that these comments should have been answers, because they explain the problem with a real life example.

Torch answered 17/8, 2012 at 7:7 Comment(5)
Except this won't work. "The string '*' cannot be used for a resource that supports credentials." w3.org/TR/cors/#resource-requestsGodthaab
@bayotop How does the browser distinguish between pages that require authentication and those with other data in the headers?Peplum
After reading the provided link, there is "supports credentials flag" which is used for this purpose. It seems to be set manually, so presumably if someone didn't know how to set up CORS correctly they could get this flag wrong as well, so I believe the above vulnerabilities are possible.Peplum
@Peplum The flag is set by the one who makes the request. Anyway, the above scenarios are examples of CSRF attacks. Allowing the '*' origin won't make you more vulnerable then you already are (maybe a little bit in rare cases). In most cases you can make the malicous cross-site request using forms so CORS doesn't matter. In cases where you need to do an AJAX request, pre-flight requests will come in the way (this is the point where the browser comes in when ACAO: '*' and Access-Control-Allow-Credentials: 'true').Godthaab
Regarding example like those, can an extension like this one be dangerous? chrome.google.com/webstore/detail/allow-cors-access-control/… In fact I've used it in a small web application of mine, and I have security concerns.Axiomatic
D
2

In scenario where server attempts to disable the CORS completely by setting below headers.

  • Access-Control-Allow-Origin: * (tells the browser that server accepts cross site requests from any ORIGIN)

  • Access-Control-Allow-Credentials: true (tells the browser that cross site requests can send cookies)

There is a fail safe implemented in browsers that will result in below error

"Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’"

So in most scenarios setting ‘Access-Control-Allow-Origin’ to * will not be a problem. However to secure against attacks, the server can maintain a list of allowed origins and whenever server gets a cross origin request, it can validate the ORIGIN header against the list of allowed origins and then echo back the same in Access-Control-Allow-Origin header.

Since ORIGIN header can't be changed by javascript running on the browser, the malicious site will not be able to spoof it.

Deerhound answered 3/8, 2020 at 7:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.