Security implications of adding all domains to COR

2019-01-16 14:56发布

问题:

It is said that instead of adding all domains to CORS, one should only add a set of domains. Yet it is sometimes not trivial to add a set of domains. E.g. if I want to publicly expose an API then for every domain that wants to make a call to that API I would need to be contacted to add that domain to the list of allowed domains.

I'd like to make a conscious trade off decision between security implications and less work.

The only security issues I see are DoS attacks and CSRF attacks. CSRF attacks can already be achieved with IMG elements and FORM elements. DoS attacks related to CORS can be overcome by blocking requests upon the referrer header.

Am I missing security implications?


===Edit===

  • It is assumed that the Access-Control-Allow-Credentials Header is not set
  • I know how to add a given list of domains "CORS access" and I'm therefore only interested in the security implications of adding all domains "CORS access"

回答1:

Cross-Site Request Forgery attacks are far and away the primary concern that Access-Control-Allow-Origin addresses.

Ryan is certainly correct regarding content retrieval. However, on the subject of making the request there is more to say here. Many web sites now provide RESTful web services that expose a wide range of features that may involve making significant changes in the backend. Very often, these RESTful services are intended to be invoked with an XHR (e.g. AJAX) request (probably with a "Single Page Application" as the front-end). If a user has an active session granting access to these services when they visit a malicious third-party site, that site may try to invoke those REST endpoints behind the scenes, passing in values that could compromise the user or the site. Depending on how the REST services are defined, there are various ways to protect against this.

In the specific case of REST web services for a Single Page App, you can dictate that all requests to the backend REST endpoints are made with XHR and refuse any non-XHR request. You can dictate this by checking for the presence of a custom request header (something like jQuery's X-Requested-With). Only XHR-type requests can set these headers; simple GET and POST requests from forms and embedded resources cannot. Finally, the reason that we want to dictate XHR requests gets us back to the original question - XHR requests are subject to CORS rules.

If you allowed Access-Control-Allow-Origin: *, then any site could make any AJAX request on the user's behalf to your REST endpoints. If your REST endpoints involve any kind of sensitive data or allow for data persistence, then this is an unacceptable security vulnerability. Instead, enforce XHR-only requests like I described and define a whitelist of origins allowed to make those requests.

It's worth pointing out that if your REST endpoints do not expose any sensitive information, or if they don't allow the user to make any persistent data changes, then Access-Control-Allow-Origin:* may be the appropriate decision. Google Maps for instance provides read-only views into public map data; there is no reason to restrict the third party sites that may wish to invoke those services.



回答2:

You can send more than one, like:

Access-Control-Allow-Origin: http://my.domain.com https://my.domain.com http://my.otherdomain.com

but I would advise against it. Instead, keep a whitelist of allowed domains. Lets say:

allowed = [ "X", "Y", "A.Z" ];

Then if you get a request from X you respond with:

Access-Control-Allow-Origin: X

If you get a request from A.Z you respond with:

Access-Control-Allow-Origin: A.Z

If you get a request from a domain that is not allowed, respond with an error or no CORS policy.

All XHR requests will send an Origin header, so use that. And you only need to send the CORS policy headers for the OPTIONS request, not the GET/POST/HEAD request that follows.


The main issue I see is that you expose all your domains. Maybe you have a secure admin domain like: https://admin.mydomain.com, or maybe you have a product website that isn't ready for launch yet. You don't want to include anything that isn't absolutely necessary for the request at hand.

And * is just extremely lazy.




回答3:

Old question, but a lot of bad answers here so I have to add mine.

If you don't set Access-Control-Allow-Credentials, and you do cookie-less authentication (ie the caller supplies a Bearer Authorization header) then you don't need to whitelist origins. Just echo the origin back in Access-Control-Allow-Origin.

A well-structured REST API can be called safely from any origin.



回答4:

CORS is about getting content back, not just making the request. When you get a resource through an img or script tag, you can trick someone's browser into making a CSRF style request. This is normal, and you can protect against that with a normal CSRF token.

With CORS enabled on all domains, you can now have javascript on an attacking site make a request and get back the content, invading their privacy.

Example:

Imagine your back enables CORS for all domains. Now I make a website that makes a request to yourimaginarybank.com/balance

An IMG request would do nothing, because my javascript can't get what was in the html of that page on your bank's website. Now that they have turned on CORS, the javascript on my site actually gets back an HTML page with your balance on it, and saves it to my server. Not only can I make a GET request like before, but now I can see what is inside. This is a huge security problem.

How to solve the problem without adding a big list into your headers? Each CORS request is made with the Origin header. The best solution is probably to read the Origin header then query a database to see if it is whitelisted as suggested by Fritz in his answer.



回答5:

Except of csauve's one, none of the replies answer my original question.

To answer my question; It seems that as long as Access-Control-Allow-Credentials is not set then there is no security problem.

(Which makes me wonder why the spec requires preflight when Access-Control-Allow-Credentials is not set?)



回答6:

Best Practice is to first check the domain of the incoming request and then generate the response header. Depending on whether this domain is allowed to send requests, you add it (just this one) to the Access-Control-Allow-Origin response header.

Afaik, it is not even possible to add more than one domain to this header. So it's either * or one specific domain and I would always prefer not to add *