CORS是一种安全的跨域AJAX请求方式吗?

时间:2011-01-31 12:12:45

标签: javascript ajax cross-domain cors

在阅读了CORS(跨源资源共享)之后,我不明白它是如何提高安全性的。如果发送了正确的ORIGIN标头,则允许跨域AJAX通信。例如,如果我发送

ORIGIN:http://example.com

服务器检查此域是否在白名单中,如果是,则标题:

Access-Control-Allow-Origin:[收到此处的网址]

与回复一起被发回(这是一个简单的案例,也有预见的请求,但问题是一样的。)

这真的很安全吗?如果有人想要收到这些信息,假冒ORIGIN标题似乎是一项非常简单的任务。此外,该标准表示该策略在浏览器中强制执行,如果Access-Control-Allow-Origin不正确,则阻止响应。显然,如果有人试图获取该信息,他将不会使用标准浏览器来阻止它。

6 个答案:

答案 0 :(得分:142)

目的是防止这种情况 -

  • 您访问网站X
  • 网站X的作者编写了一个恶意脚本,并将其发送到您的浏览器
  • 在您的浏览器上运行的脚本会登录到您的银行网站并执行恶意内容,并且因为它在您的浏览器中以的身份运行,它有权这样做。

我们的想法是,您的银行网站需要某种方式告诉您的浏览器是否应该信任网站X上的脚本来访问您银行的网页。

答案 1 :(得分:54)

只是添加@jcoder的答案,Origin标题的重点不是保护服务器上请求的资源,该任务通过其他方式由服务器本身决定,正是因为攻击者确实能够使用适当的工具来欺骗这个标题。

Origin标题的重点是保护用户。 方案如下:

  • 攻击者创建恶意网站M

  • 用户Alice被欺骗连接到M,其中包含尝试通过CORS在实际支持CORS的服务器B上执行某些操作的脚本

  • B可能在其Access-Control-Allow-Origin标题中没有M,原因为何?

  • 关键点是,M无法欺骗或覆盖Origin标头,因为请求是由Alice的浏览器发起的。因此,她的浏览器会将(正确的)Origin设置为M,这不在B的Access-Control-Allow-Origin中,因此请求将失败。

现在,爱丽丝可以自己改变Origin标题,但为什么会这样,因为这意味着她会伤害自己?

TL; DR:Origin标题保护无辜的用户。它不保护资源。攻击者可以在自己的机器上进行欺骗,但不能在不受他控制的机器上进行欺骗。

服务器仍应保护其资源,因为匹配的Origin标头并不意味着授权访问。但是,Origin标头不匹配,表示未经授权的访问。

答案 2 :(得分:47)

它并非旨在阻止人们获取数据。如果没有人得到它,你就无法揭露它。

它被设计为给定:

  • Alice,提供API的人,可通过Ajax访问
  • Bob,一位拥有网络浏览器的人
  • 查理,第三方运营自己的网站

如果Bob访问Charlie的网站,那么Charlie无法将JS发送到Bob的浏览器,以便从Alice的网站获取数据并将其发送给Charlie。

如果Bob在Alice的网站上有一个用户帐户,允许他做帖子评论或删除数据等事情,上述情况就变得更加重要了 - 因为没有保护,Charlie可以告诉Bob的浏览器在Bob的背后做这件事。

如果您想阻止未经授权的人查看数据,则需要使用密码,SSL客户端证书或其他基于身份的身份验证/授权方法进行保护。

答案 3 :(得分:14)

同一原产地政策的目的不是阻止人们普遍访问网站内容;如果有人想这样做,他们甚至不需要浏览器。重点是阻止客户端脚本访问另一个域上的内容而没有必要的访问权限。请参阅Same Origin Policy的维基百科条目。

答案 4 :(得分:5)

在阅读了有关CORS之后,我并不了解它如何提高安全性。

CORS不会提高安全性。 CORS为服务器提供了一种机制,告诉浏览器外部域应该如何访问它们,并且它尝试以与CORS之前存在的浏览器安全模型(即Same Origin Policy)一致的方式执行此操作。 / p>

但同源策略和CORS的范围有限。具体来说,CORS specification本身没有拒绝请求的机制。它可以使用标头告诉浏览器不要让来自外部域的页面读取响应。并且,在预检请求的情况下,它可以要求浏览器不发送来自外部域的某些请求。但CORS没有指定服务器拒绝(即不执行)实际请求的任何方法。

让我们举个例子。用户通过cookie登录到站点A。用户加载恶意网站M,该网站会尝试提交执行POSTA的表单。会发生什么?好吧,有或没有CORS,并且有或没有M是允许的域,浏览器将使用用户的授权cookie将请求发送到A,服务器将执行恶意POST就像用户启动它一样。

此攻击称为Cross-Site Request Forgery,CORS本身无法缓解此攻击。这就是为什么如果您允许代表用户更改数据请求,CSRF保护如此重要。

现在,使用Origin标头可以成为CSRF保护的重要组成部分。实际上,检查它是current recommendation for multi-pronged CSRF defense的一部分。但是Origin标头的使用超出了CORS规范。

总之,CORS是一个有用的规范,用于将现有的同源策略安全模型扩展到其他接受域。它没有增加安全性,站点需要与CORS之前相同的防御机制。

答案 5 :(得分:1)

我迟到了回答但我不认为这里的任何帖子确实提供了所寻求的答案。最大的问题应该是浏览器是编写origin标头值的代理。恶意脚本无法写入origin标头值。当服务器使用Access-Control-Allow-Origin标头回复时,浏览器会尝试确保此标头包含先前发送的origin值。如果不是,则会触发错误,并且不会将值返回给请求脚本。这个问题的其他答案提供了一个很好的场景,当你想要拒绝回答邪恶的剧本。

@daniel f也为问题提供了一个很好的答案