设置访问控制-允许-起源接受所有域时存在哪些安全风险?

我最近不得不将 Access-Control-Allow-Origin设置为 *,以便能够进行跨子域 AJAX 调用。我觉得这可能是个安全问题。如果我一直保持这个设置,会有什么风险?

81749 次浏览

通过响应 Access-Control-Allow-Origin: *,请求的资源允许与每个原点共享。这基本上意味着任何站点都可以向您的站点发送 XHR 请求并访问服务器的响应,如果您没有实现这个 CORS 响应,就不会出现这种情况。

因此,任何网站都可以代表访问者向您的网站提出请求,并处理其响应。如果你有一些实现,比如基于浏览器自动提供的认证或授权方案(cookie、基于 cookie 的会话等) ,第三方站点触发的请求也会使用它们。

这确实会带来安全风险,特别是如果您不仅允许对选定的资源,而且允许对每个资源进行资源共享。在这种情况下,您应该看看 什么时候启用 CORS 是安全的

更新(2020-10-07)

当前的 去找标准公司在凭据模式设置为 include时省略凭据,如果 Access-Control-Allow-Origin设置为 *

因此,如果使用基于 Cookie 的身份验证,则不会在请求中发送凭据。

访问控制-允许-起源只是一个从服务器发送到浏览器的 http 头。将它限制在一个特定的地址(或禁用它)不会使您的站点更安全,例如,对于机器人。如果机器人愿意,他们可以忽略标题。默认情况下,普通浏览器(IE、 Chrome 等等)会尊重标题。但是像 邮差这样的应用程序只是忽略它。

当服务器端返回响应时,它实际上并不检查请求的“原点”是什么。它只是添加了 http 头。发送请求的浏览器(客户端)决定读取访问控制头并对其采取行动。注意,在 XHR 的情况下,它可能会使用一个特殊的‘ OPTION’请求来首先请求标头。

因此,任何具有创造性脚本能力的人都可以轻易地忽略整个标题,无论其中设置了什么。

参见 设置访问控制-允许-原点时可能出现的安全问题


现在回答我的问题

我不禁觉得我把我的环境置于安全之上 风险。

如果有人想攻击你,他们可以很容易地绕过访问控制允许起源。但是通过启用“ *”,你确实给攻击者提供了更多的“攻击向量”,比如使用支持 HTTP 头的常规浏览器。

这里有两个例子,当通配符真的有问题的时候,以注释的形式发布:

假设我登录我的银行网站,如果我进入另一个页面,然后 回到我的银行,我仍然登录,因为一个饼干。其他 互联网上的用户可以在我的银行点击相同的网址,因为我这样做,但 没有 cookie 他们就无法进入我的账户。如果 允许跨来源请求,恶意网站可以有效地 模拟用户。

布拉德

假设您有一个公共的家庭路由器,如 LinksysWRT54g 或 假设路由器允许跨源请求 在我的网页可以使 HTTP 请求到公共路由器的 IP 地址 (例如192.168.1.1)及重新设定你的路由器以容许攻击 甚至可以直接使用你的路由器作为 DDoS 节点 允许 ping 或简单 HTTP 服务器检查的测试页面 可能会被大量滥用。)

布拉德

我觉得这些评论应该是答案,因为它们用一个现实生活中的例子来解释这个问题。

Access-Control-Allow-Origin: *完全可以安全地添加到任何资源中,即 除非,该资源包含受标准凭据以外的其他东西保护的私有数据。标准凭据是 cookie、 HTTP 基本认证和 TLS 客户端证书。

受 cookie 保护的数据是安全的

想象一下 https://example.com/users-private-data,它可能根据用户的登录状态公开私有数据。此状态使用会话 cookie。将 Access-Control-Allow-Origin: *添加到这个资源中的是 安全,因为这个头只允许在没有 cookie 的情况下发出请求时访问响应,而 cookie 是获取私有数据所必需的。因此,不会泄露任何私有数据。

例如: 受位置/ip/内部网络保护的数据不安全(不幸的是,这在内部网和家用电器中很常见) :

想象一下 https://intranet.example.com/company-private-data,它公开公司的私人数据,但是只有在公司的 wifi 网络上才能访问这些数据。将 Access-Control-Allow-Origin: *添加到这个资源中的是 不安全,因为它使用标准凭据以外的东西进行保护。否则,错误的脚本可能会将您用作通往内部网的通道。

经验法则

想象一下,如果用户在一个匿名窗口中访问资源,他们会看到什么。如果您对每个人都能看到这些内容(包括浏览器接收到的源代码)感到满意,那么添加 Access-Control-Allow-Origin: *是安全的。

在这种情况下,服务器试图通过设置以下消息头来完全禁用 CORS。

  • 访问-控制-允许-起源: * (告诉浏览器服务器接受 来自任何来源的跨地点要求)

  • 访问-控制-允许-凭据: true (告诉浏览器 站点请求可以发送 Cookie)

在浏览器中实现了一个故障保护,将导致以下错误

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

因此,在大多数情况下,将“访问控制-允许-起源”设置为 *不成问题。然而,为了防范攻击,服务器可以维护一个允许来源的列表,每当服务器收到跨来源请求时,它可以根据允许来源的列表验证 ORIGIN 标头,然后在 Access-Control-Allow-ORIGIN 标头回显相同的内容。

由于运行在浏览器上的 javascript 无法更改 ORIGIN 头,恶意站点将无法欺骗它。

这个答案最初是作为对 What are the security implications of setting Access-Control-Allow-Headers: *, if any?的答复而写的,尽管与这个问题无关,但它被合并了。


要将其设置为通配符 *,意味着允许除 安全登记的之外的所有标头,并取消保证它们安全的限制。

以下是4个安全标题被认为是安全的限制:

  • 对于 Accept-Language 和 Content-Language: 只能有包含 0-9A-Za-z、空格或 *,-.;=的值。
  • 对于 Accept 和 Content-Type: 不能包含 CORS 不安全的请求头字节: 0x00-0x1F(允许的 0x09(HT)除外)、 "():<>?@[\]{}0x7F(DEL)。
  • 对于 Content-Type: 需要一个解析值(忽略参数)为 application/x-www-form-urlencodedmultipart/form-datatext/plain的 MIME 类型。
  • 对于任何头: 值的长度不能大于128。

为了简单起见,我将根据这些标题给出答案。

根据服务器实现的不同,简单地删除这些限制可能非常危险(对用户而言)。
例如,这个过时的 wordpress 插件有一个反射的 XSS 漏洞,其中 Accept-Language的值被解析并按原样呈现在页面上,如果该值中包含恶意有效负载,则会导致在用户的浏览器上执行脚本。

使用通配符头 Access-Control-Allow-Headers: *,第三方站点重定向到您的站点可以将头的值设置为 Accept Language: <script src="https://example.com/malicious-script.js"></script>,因为通配符消除了上面第1点中的限制。

飞行前的响应会给这个请求开绿灯,然后用户会被重定向到你的站点,在他们的浏览器上触发一个 XSS,其影响范围从恼人的弹出窗口到通过 cookie 劫持失去对他们帐户的控制。

因此,我强烈建议不要设置通配符,除非设置通配符的 API 端点没有在页面上呈现任何内容。

您可以将 Access-Control-Allow-Headers: Pragma设置为问题的替代解决方案。


请注意,值 *仅计算为无凭据请求(没有 HTTP cookie 或 HTTP 身份验证信息的请求)的特殊通配符值,否则将作为文本头读取。文件