CORS如何为用户提供至少一定的安全性?

7

首先要道歉的是:对我来说,这似乎是一个“愚蠢”的问题,我相信不久之后我会后悔甚至问这个问题……但是我现在无法理解,因为我的思维似乎被卡在错误的路上。所以请耐心地和我一起解决:

我理解“同源策略”对于Web服务来说很麻烦,而CORS松开了限制,使Web服务能够合理地工作,同时仍然为用户提供良好的安全性。我的问题是:CORS究竟是如何做到这一点的?

假设用户访问网站A,该网站提供的代码会向网站Z发出Web服务请求。但是我已经侵入并破坏了网站Z,并将其变成攻击站点。我迅速让它对所有CORS请求做出积极回应(header add Access-Control-Allow-Origin:“*”)。不久之后,用户的计算机就会被我的攻击从Z中攻陷。

在我看来,用户从未直接访问过Z,也不知道Z的存在,也从未“批准”过Z。而且,在入侵事件被发现之后,网站A似乎无法阻止它发生(除非自己下线:-))。难道不应该是安全问题要求A认证Z,而不是Z认证A吗?我错过了什么?


1
通过选择首先向其发出Web服务请求,可以有效地证明Z已经得到了认证。 - Barmar
那个东西,就像孩子们说的那样,“很神奇”。 - qooplmao
1
所以看起来从被篡改的网站中获取正确的CORS头实际上确实完全取消了浏览器的“同源”策略,对吗?那么为什么要让浏览器实现CORS,而不是让它们放松其“同源”策略呢?使用OAuth难道不是在实际上承认CORS提供的用户安全性极低吗?如果网站A通过提供使用Z的Javascript代码来“认证”网站Z(在其被篡改之前),那么从用户的角度来看,CORS是否真的完全无关紧要?CORS对其他人是否像对我一样毫无意义? - Chuck Kollars
另外请注意:CORS 不应被用作安全机制!CORS 只是服务器指示它期望跨源请求的一种方式。用户认证与 CORS 无关。 - monsur
1
我担心我们在谈论不同的事情。一个常见的问题 - 但这里不是我的问题 - 是提供服务的网站(在这种情况下是Z)的安全性 - 没有收费错误,没有更改否认,没有未经授权的访问等。相反,我关注的是浏览器用户的安全性。从用户的角度来看,问题在于Z(他实际上从未访问过,也从未收到过账单,可能甚至不知道其存在)在他的计算机上放置了恶意软件。 - Chuck Kollars
显示剩余2条评论
3个回答

6
我也在调研这个问题,我的思路跟你类似。据我新的理解:CORS并不提供安全性,而是规避安全性以提供功能性。通常浏览器不允许跨域请求;如果你访问shady.com,那里有一个脚本试图使用你机器上的cookie访问bank.com,则shady.com的脚本将能够使用该cookie来冒充你在bank.com上执行操作。为了防止这种情况,bank.com不会将其API标记为CORS可用,这样当shady.com的脚本开始HTTP请求时,浏览器会阻止请求。
因此,same-origin保护用户免受自身影响,因为他们不知道授权cookie的存在; CORS允许拥有用户资源的服务器标记API可从其他站点的脚本访问,这将导致浏览器忽略其自身的跨域保护策略。
(任何更好地理解这一点的人,请在需要时添加或更正!)

关于:为了防止这种情况发生,bank.com 不会将其 API 标记为 CORS 启用,因此当 shady.com 的脚本开始 HTTP 请求时,浏览器本身会阻止该请求。问题是:浏览器如何在不知道远程服务器是否允许跨域请求的情况下阻止请求? - Koray Tugay
@KorayTugay 在尝试访问该API之前,浏览器实际上会进行初始请求以确定这一点-请参见https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request - Rollie
在我看来,非常重要的一点是要提到预检请求仅针对特定方法执行,具体来说,它们不适用于 GET 和 POST 方法,而这些方法 shaddy.com 可能会尝试使用。 - Koray Tugay
我不知道!我查了一下,听起来可能会根据内容类型发送POST的预检请求等:https://dev59.com/zVkS5IYBdhLWcg3wiXMj - Rollie

4
CORS对安全没有帮助。但它确实允许出售Web字体的人决定哪些网站可以轻松获得他们的字体。这几乎是唯一的用例。
用户在引入CORS之前和之后的感知没有任何区别。请记住,在CORS之前,跨域请求也能正常工作(人们经常抱怨必须使用jQuery来支持IE上的CORS……但在IE中,你只需要发送请求即可获得响应,不需要额外的努力……它只是有效的)。
一般来说,信任模型是反过来的。正如其他人所说,通过引用其他站点,你已经暗示了信任……因此,请给我该死的数据!

0

CORS(跨域资源共享)保护接收请求的网站(在您的示例中为Z)免受发出请求的网站(在您的示例中为A)的攻击,通过告诉用户的浏览器谁有权或无权查看请求的响应。

当JavaScript应用程序要求浏览器向与其自身不同的源发出HTTP请求时,浏览器不知道这两个源之间是否存在相互协议以进行此类调用。当然,如果请求来自源A,则A同意(并且A对其用户负责,如果Z是恶意的),但是接收方Z同意吗?浏览器了解的唯一方法是询问Z,并通过实际执行请求来完成。除非Z明确允许A接收响应,否则浏览器将不允许A的应用程序读取它。

您是正确的,CORS的唯一作用是放宽同源策略。在此之前,允许跨源请求,并且浏览器会自动包含其目标的cookie,也就是说,它会向Z发送一个已验证请求。这意味着,如果没有同源策略,A可以像用户一样浏览Z,查看其数据等。同源策略解决了这个非常严重的安全漏洞,但由于某些服务仍然需要有时使用跨源请求,因此创建了CORS。

请注意,CORS并不能阻止请求被发送,因此如果A的JS应用程序向Z发送一个请求,要求将所有用户的钱发送到某个帐户,Z将接收到这个请求,其中包含所有的cookie。这称为跨站点请求伪造(CSRF)。有趣的是,对抗这种类型攻击的主要防御措施基于CORS。它要求请求中有一些秘密值(“CSRF令牌”),只能通过跨源请求获取,如果A不在Z的授权列表上,则无法获取。现在,同站点cookie也可以使用,它们更易于管理,但在跨域方面无法工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接