Closed defransen closed 6 years ago
I agree, an example of a more strict control will be helpful
Access-Control-Allow-Origin "*"
is an extremely bad advise. Especially since it is the only one and no discussion on it, making people new to the topic believe there is just this wildcard setting.
I can't believe this is linked to someone who wrote a book on CORS.
I am referring to https://enable-cors.org/server_apache.html which comes up as a top search result on Google when searching for cors & apache httpd.
There is never a reason to use a wildcard. In fact, I consider it a big problem that the wildcard is even a supported feature by the CORS spec and browsers.
There should only be an example with one or more specific hostnames, and no mention of wildcards at all, so people don't get the wrong idea (or say "there is also the option of a wildcard, but that's bad, because now all the protections that browsers added over many years are suddenly completely gone and your site just opened a major attack vector").
@monsur Looks like this line was added to the website 5 years ago, do you still recommend using a wildcard for most projects?
<p>For simple CORS requests, the server only needs to add the following header to its response:</p>
<p><code>Access-Control-Allow-Origin: *</code></p>
If not, I've create a PR to purge the mention of it. 👍
There is a reason to use *
– it's for code libraries that are supposed to be publicly distributed through CDNs, e.g. https://code.jquery.com/jquery-3.3.1.slim.min.js or https://unpkg.com/react@16.2.0/umd/react.production.min.js, but it definitely should NOT be a default option.
I agree, this is unconscionably bad advise. Essentially, the first page of this site is explaining to users how to break the fundamental security of their site without any explanation or even the slightest warning! If they have authenticated resources using cookies for auth, it is now trivial CSRF for any attacker to execute any API call on the user's behalf. At the very least it must be stated that wildcard origins is only acceptable for public resources that make no use of cookies for authenticated functionality in any way.
@monsur why have you not responded to this yet?
@all: please complain at google and all other search engines about showing that site with extremely bad information on page one, please suggest delisting that irresponsible advice. Also please write many blog posts about how bad that advice is with a clear reference to the authors website. The author had enough time to correct that very bad advice, it is now time that responsible admins and developers take all possible steps to make that site disappear from the web. Thanks for your support!
Yes, I am angry. I just had to spend half day to correct some problematic site configurations - and of course the devs pointed me to that enable-cors example from the authors site as their source of reference and once again I had that disussion and again I had to explain to somebody that the "authoritative website" about cors is spreading pure bs - it is unbelievable that this joke website still exists and causes so much trouble and so many serious problems with people faithfully taking advice "from that cors guru" - a dangerous misuse of his perceived position as an authority in that area. #unfit.
Google, DDG and others: please make it disappear at least from search results, thanks.
... and thus rendering the idea of cross-origin resource security useless, because every one can present your resources as his own. I think the basic default setup should be to respond with the content of the received Origin header in the Access-Control-Allow-Origin header. This prevents at least unwanted "proxying" of your resources.
I would like to add, that using the content of Origin
header as default is probably even more insecure then using *
by default as it can hinder browser's ability to prevent a certain types of attacks.
Consider the following 2 examples, in the the 1st one browser helps prevent the attack, in the second one, it does not.
1st example
An api.example.com
sends wildcard like Access-Control-Allow-Origin: *
header as a default behaviour. A legitimate page page.example.com
needs to use the API through a Fetch request. It can do it, as well as an attacker's site attacker.example.com
. However, if api.example.com
is protected by cookies, none of the sites will be able to use credentialed request to api.example.com
, because a browser would not allow it. In order to allow it api.example.com
will need to send Access-Control-Allow-Credentials header, like Access-Control-Allow-Credentials: true
. Here comes the problem, this combination of headers would allow both page.example.com
and attacker.example.com
to send credentialed request to api.example.com
and examine the response, but, luckily, credentialed requests with wildcard are not allowed: Credentialed requests and wildcards. E.g., if you try to exploit such a misconfiguration in Chrome
you will receive an error: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
Thus, while testing this functionality the developer will quickly discover that to enable credentialed requests to api.example.com
from page.example.com
, api.example.com
's header Access-Control-Allow-Origin: *
, must be replaced with Access-Control-Allow-Origin: https://page.example.com
.
2nd example
Everything is set up in the same as in the 1st example, except instead of Access-Control-Allow-Origin: *
by default, api.example.com
sends Access-Control-Allow-Origin: <Origin from request headers>
. Now, as soon as the developer enables Access-Control-Allow-Credentials: true
, the browser will allow credentialed requests coming from both page.example.com
and attacker.example.com
as response headers include Access-Control-Allow-Credentials: true
and Access-Control-Allow-Origin: https://page.example.com
or Access-Control-Allow-Origin: https://attacker.example.com
respectively. Thus, this vulnerability can go unnoticed.
So defaulting Access-Control-Allow-Origin to Origin header of a request disables built-in browser attack prevention mechanism.
The steps should be:
1) Don't enable CORS unless you have to.
2) Enable CORS only for whitelisted origins and protocols. Because Access-Control-Allow-Origin
only allows a single domain or wildcard, in this case you can use the request's Origin
header in Access-Control-Allow-Origin
only if it's explicitly whitelisted on the server side.
3) If a purpose of your servers is to distribute content, requested on behalf of a user, with intention of it being publicly available to any part of 3rd party web page, then *
can be used.
@aschatten One note: The restriction to Access-Control-Allow-Origin: *
and Access-Control-Allow-Credentials: true
didn't exist yet, when I opened this issue.
Your example isn't what I ment with "proxying" (There is no proxy involved at all). My scenario means cases where another server acts like it would provide the same service as your server, but simply proxies to your server. If you send "*" in Access-Control-Allow-Origin
it is possible to create setups where your server isn't able to detect that the request comes from another server and not from normal web-clients.
But you are right that just sending back the received Origin
doesn't make it more secure from the client-side perspective. The service is public and can be used by any website.
If a developer allows credentials he realy should check the Origin
header with a whitelist, or if the service should be usable by any website take steps to secure the credentials (signed cookies for example)
Edit: While I re-thought the issue now I have to admit that it is possible to proxy your server even without the usage of "*", thus making my initial issue pointless
... and thus rendering the idea of cross-origin resource security useless, because every one can present your resources as his own. I think the basic default setup should be to respond with the content of the received
Origin
header in theAccess-Control-Allow-Origin
header. This prevents at least unwanted "proxying" of your resources.