41

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

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

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

我错过了安全隐患吗?


===编辑===

  • 假设Access-Control-Allow-Credentials没有设置Header
  • 我知道如何添加给定的域“CORS 访问”列表,因此我只对添加所有域“CORS 访问”的安全隐患感兴趣
4

6 回答 6

28

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

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

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

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

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

于 2013-11-25T07:22:11.880 回答
15

老问题,但这里有很多不好的答案,所以我必须添加我的。

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

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

于 2016-12-08T06:09:13.590 回答
11

您可以发送多个,例如:

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

但我建议不要这样做。相反,保留允许域的白名单。让我们说:

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

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

Access-Control-Allow-Origin: X

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

Access-Control-Allow-Origin: A.Z

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

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


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

而且*非常懒惰。


于 2013-10-11T16:37:41.733 回答
4

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

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

例子:

想象一下,您的背部为所有域启用了 CORS。现在我创建了一个向 yourimaginarybank.com/balance 发出请求的网站

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

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

于 2013-11-24T21:53:18.290 回答
2

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

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

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

于 2017-09-21T11:35:12.237 回答
-1

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

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

于 2013-10-11T16:33:35.363 回答