javascript 将所有域添加到 CORS 的安全隐患(Access-Control-Allow-Origin:*)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19322973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 15:10:06  来源:igfitidea点击:

Security implications of adding all domains to CORS (Access-Control-Allow-Origin: *)

javascripthtmlsecuritycorsdenial-of-service

提问by brillout

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.

据说不是将所有域都添加到CORS 中,而应该只添加一组域。然而,有时添加一组域并非易事。例如,如果我想公开一个 API,那么对于每个想要调用该 API 的域,我都需要联系我将该域添加到允许的域列表中。

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

我想在安全影响和减少工作之间做出有意识的权衡决定。

The only security issues I see are DoS attacksand CSRFattacks. 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.

我看到的唯一安全问题是DoS 攻击CSRF攻击。CSRF 攻击已经可以通过 IMG 元素和 FORM 元素实现。可以通过阻止引用标头上的请求来克服与 CORS 相关的 DoS 攻击。

Am I missing security implications?

我是否遗漏了安全隐患?



===Edit===

===编辑===

  • It is assumed that the Access-Control-Allow-CredentialsHeader 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"
  • 假设Access-Control-Allow-Credentials未设置 Header
  • 我知道如何添加给定的域列表“CORS 访问”,因此我只对添加所有域“CORS 访问”的安全影响感兴趣

采纳答案by brillout

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

除了csauve的一个,没有一个回复回答我原来的问题。

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

回答我的问题;好像只要Access-Control-Allow-Credentials不设置就没有安全问题。

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

(这让我想知道为什么规范需要在Access-Control-Allow-Credentials未设置时进行预检?)

回答by Jake Feasel

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

跨站点请求伪造攻击是 Access-Control-Allow-Origin 解决的主要问题。

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.

关于内容检索,Ryan 当然是正确的。但是,关于提出请求,这里还有更多话要说。许多网站现在提供 RESTful Web 服务,这些服务公开了可能涉及在后端进行重大更改的广泛功能。通常,这些 RESTful 服务旨在通过 XHR(例如 AJAX)请求(可能使用“单页应用程序”作为前端)来调用。如果用户在访问恶意第三方站点时有一个活动会话授予对这些服务的访问权限,则该站点可能会尝试在幕后调用这些 REST 端点,传递可能危及用户或站点的值。根据 REST 服务的定义方式,有多种方法可以防止这种情况发生。

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.

在用于单页应用程序的 REST Web 服务的特定情况下,您可以规定对后端 REST 端点的所有请求都是使用 XHR 发出的,并拒绝任何非 XHR 请求。您可以通过检查是否存在自定义请求标头(类似于 jQuery 的 X-Requested-With)来规定这一点。只有 XHR 类型的请求可以设置这些标头;来自表单和嵌入式资源的简单 GET 和 POST 请求不能。最后,我们想要规定 XHR 请求的原因让我们回到最初的问题——XHR 请求受 CORS 规则的约束。

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.

如果您允许Access-Control-Allow-Origin: *,则任何站点都可以代表用户向您的 REST 端点发出任何 AJAX 请求。如果您的 REST 端点涉及任何类型的敏感数据或允许数据持久化,那么这是一个不可接受的安全漏洞。相反,像我描述的那样强制执行仅限 XHR 的请求,并定义允许发出这些请求的来源白名单。

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.

值得指出的是,如果您的 REST 端点不公开任何敏感信息,或者如果它们不允许用户进行任何持久的数据更改,那么Access-Control-Allow-Origin: *可能是适当的决定。例如,谷歌地图提供公共地图数据的只读视图;没有理由限制可能希望调用这些服务的第三方站点。

回答by csauve

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.

如果您没有设置Access-Control-Allow-Credentials,并且您进行无 cookie 身份验证(即调用方提供一个 Bearer Authorization 标头),那么您不需要将来源列入白名单。只需在Access-Control-Allow-Origin.

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

可以从任何来源安全地调用结构良好的 REST API。

回答by Halcyon

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 Xyou respond with:

然后,如果您收到来自X您的请求,请回复:

Access-Control-Allow-Origin: X

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

如果您收到来自A.Z您的请求,请回复:

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.

如果您收到来自不允许的域的请求,请使用错误或无 CORS 策略进行响应。

All XHR requests will send an Originheader, so use that. And you only need to send the CORS policy headers for the OPTIONSrequest, not the GET/POST/HEADrequest that follows.

所有 XHR 请求都将发送一个Origin标头,因此请使用它。并且您只需要发送OPTIONS请求的 CORS 策略标头,而不是GET/POST/HEAD随后的请求。



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.

我看到的主要问题是您公开了所有域。也许您有一个安全的管理域,例如:https://admin.mydomain.com,或者您的产品网站尚未准备好发布。您不想包含对于手头的请求不是绝对必要的任何内容。

And *is just extremely lazy.

并且*非常懒惰。



回答by Ryan

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.

CORS 是关于取回内容,而不仅仅是提出请求。当您通过 img 或 script 标签获取资源时,您可以欺骗某人的浏览器发出 CSRF 样式的请求。这是正常的,您可以使用普通的 CSRF 令牌来防止这种情况发生。

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.

在所有域上启用 CORS 后,您现在可以让攻击站点上的 javascript 发出请求并取回内容,从而侵犯他们的隐私。

Example:

例子:

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

想象一下,您的背部为所有域启用 CORS。现在我创建了一个向 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.

IMG 请求什么也不做,因为我的 javascript 无法获取您银行网站上该页面的 html 中的内容。既然他们已经打开了 CORS,我网站上的 javascript 实际上会返回一个带有您的余额的 HTML 页面,并将其保存到我的服务器。我不仅可以像以前一样发出 GET 请求,而且现在我可以看到里面的内容了。这是一个巨大的安全问题。

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.

如何在不向标题中添加大列表的情况下解决问题?每个 CORS 请求都是使用 Origin 标头发出的。最好的解决方案可能是读取 Origin 标头,然后查询数据库以查看它是否如 Fritz 在他的回答中所建议的那样被列入白名单。

回答by devnull69

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-Originresponse header.

最佳实践是首先检查传入请求的域,然后生成响应头。根据是否允许此域发送请求,将它(仅此一个)添加到Access-Control-Allow-Origin响应标头中。

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 *

Afaik,甚至不可能向此标头添加多个域。所以它是一个*或一个特定的域,我总是不想添加*