如何阻止恶意代码欺骗“ Origin”标头来利用CORS?


142

据我了解,如果在foo.com页面上运行的客户端脚本想要从bar.com请求数据,则在请求中必须指定标头Origin: http://foo.com,而bar必须以响应Access-Control-Allow-Origin: http://foo.com

有什么方法可以阻止roh.com网站上的恶意代码简单地欺骗标头Origin: http://foo.com从bar请求页面?


2
我认为要点是,提供页面的原始域(在此处foo.com)必须提供Access-Control-Allow-Origin标头,否则浏览器不允许该请求bar.com
克里斯·海斯

2
通过阅读这篇文章真的帮了我在我的浏览器,源服务器和目标服务器之间的CORS过程的理解。html5rocks.com/en/tutorials/cors
brendonparker 2014年

5
@ChrisHayes这根本不是CORS的工作方式。您可以通过查看规范该主题的MDN Wiki页面上的内容来进一步阅读
Ray Nicholus 2014年

1
@brendonparker是的,那是一篇很棒的文章。那位作者回答了许多有关SO的CORS问题,并且还维护了enable-cors.org
Ray Nicholus 2014年

4
@RayNicholus有趣的是,我显然已经离开了。感谢您的链接。通过对我的评论的投票来判断,我并不是唯一遭受这种幻想困扰的人。我希望那两个人回来学习(并删除他们的选票!)。
克里斯·海斯

Answers:


149

浏览器可以控制Origin标题的设置,用户无法覆盖此值。因此,您不会看到Origin来自浏览器的标头。恶意用户可以制作手动设置Origin标头的curl请求,但是该请求将来自浏览器外部,并且可能没有特定于浏览器的信息(例如cookie)。

请记住:CORS不是安全的。不要依靠CORS保护您的网站。如果您要提供受保护的数据,请使用Cookie或OAuth令牌或Origin标头以外的其他内容来保护该数据。Access-Control-Allow-OriginCORS中的标头仅指示应允许哪个起源发出跨域请求。不要再依赖它了。


3
这很有意义。如果浏览器不允许JavaScript覆盖Origin标头,则没有问题。如果您正在从浏览器外部执行请求,则不会有Cookie。我想我很困惑,因为在我正在阅读的所有文档中,都没有明确指出不能重写Origin标头。谢谢!
杰伊·拉蒙特

41
如果有人想欺骗某些东西,那么他们可以这样做。他们几乎可以使用任何脚本语言来构造http请求。Perl和Python具有http库,这使此操作非常容易。这些库存储和发送cookie,让您添加任意头,并提供大量调试信息。因此,CORS标头只是为了使您在论坛上读取恶意javascript更加困难,从而使您在浏览器中都登录到另一个域时,会对另一个域上的银行帐户造成不良影响。
Mnebuerquo 2014年

9
只是要澄清一下,恶意用户可以简单地生成一个已打补丁的浏览器实例,以允许他们手动控制Origin头,然后完美地模仿普通用户,Cookie,AJAX等等。
Jordan Rieger 2014年

10
“浏览器可以控制Origin头的设置,用户不能覆盖此值。” 我确信一旦请求离开浏览器,使用Fiddler2或Charles这样的工具来修改标头就非常容易。
2015年

3
恶意用户可以简单地产生一个已打补丁的浏览器实例,以允许他们手动控制Origin标头。如果您可以访问计算机,就可以“简单地产生一个打补丁的浏览器实例”(实际上听起来并不那么简单)对我来说),为什么不直接从磁盘读取cookie?它们以纯文本格式存储,您知道。在现实生活中,跨站点脚本编写是一个真正的威胁,而您的攻击方案只是人为的并且不切实际。
Stijn de Witt

35

TLDR:没有什么能阻止恶意代码欺骗来源。发生这种情况时,您的服务器将永远不知道它,并将根据请求采取行动。有时,这些请求很昂贵。因此,请勿使用CORS代替任何类型的安全性。


我最近一直在和CORS玩耍,我也问过自己同样的问题。我发现,浏览器可能足够聪明,可以在看到欺骗性的CORS请求时知道它,但是您的服务器却不那么聪明。

我发现的第一件事是Origin标头是HTTP 禁止的标头名称,无法以编程方式进行修改。这意味着您可以使用Google Chrome的“修改标题”在大约8秒钟内对其进行修改

为了测试这一点,我设置了两个客户端域和一个服务器域。我在服务器上添加了一个CORS白名单,该白名单允许来自客户端1的CORS请求,但不允许来自客户端2的CORS请求。我测试了两个客户端,确实客户端1的CORS请求成功,而客户端2的失败。

然后,我欺骗了客户端2的Origin标头以匹配客户端1的标头。服务器接收到欺骗性的Origin标头,并成功通过了白名单检查(如果您是半杯半空的家伙,则失败)。此后,服务器通过消耗其计划使用的所有资源(数据库调用,发送昂贵的电子邮件,发送甚至更昂贵的sms消息等)来尽职地执行任务。完成后,服务器会愉快地将欺骗的Access-Control-Allow-Origin标头发送回浏览器。

我阅读的文档指出,Access-Control-Allow-Origin接收到的值必须与Origin请求中发送的值完全匹配。它们确实匹配,所以当我在Chrome中看到以下消息时,我感到很惊讶:

XMLHttpRequest无法加载http://server.dev/test。“ Access-Control-Allow-Origin”标头的值http://client1.dev 不等于提供的来源。http://client2.dev 因此,不允许访问原点。

我阅读的文档似乎并不准确。Chrome的网络标签清楚地将请求标头和响应标头都显示为http://client1.dev,但是您会在错误中看到Chrome以某种方式知道真实来源,http://client2.dev并正确拒绝了响应。这无关紧要,因为服务器已经接受了欺骗的请求并花了我的钱。


2
@Nocturno,谢谢你的例子。让我补充一下我的看法。CORS与浏览器安全功能有关。如果将安全浏览器从其原始状态进行了修改,则可以解释为该浏览器可能缺少安全功能。
LukaŽitnik'3

10
一点都不出色。它完全错过了CORS的要点。如果您可以拦截来自用户计算机的请求,则可以读取他们的cookie,安装键盘记录程序,病毒和所有其他实际威胁。CORS可以保护诚实用户登录到站点A,使其免受恶意脚本的侵害,而该恶意脚本又以某种方式注入到站点B。站点B上的脚本(可能是论坛帖子中未被站点B正确转义的Javascript的摘要)可以执行在用户的帐户下内设有一个动作(如删除的东西等),利用从网站A的会话cookie
斯泰恩德威特

3
这被称为跨站点脚本编写,并且无需CORS就可以完成,而无需获得对用户计算机的控制权。这就是重点。不需要控制用户的计算机,因为在向站点A发出请求时,浏览器用于将会话cookie自动添加到请求中,因此它看起来像是来自用户本身的有效请求,而实际上它是来自其他脚本的。现场。同源策略阻止了这种情况,并且CORS用于将应被授予访问权限的域列入白名单,即使它们位于不同的来源。
Stijn de Witt

3
@Nocturno是的,我可能有点太粗糙了,对此感到抱歉。您原来的观点。同源策略是浏览器的安全功能,而CORS是一种通过将某些域列入白名单来削弱该安全性的机制。OP需要了解,欺骗Origin标头作为“攻击”实际上是不可行的,因为它不会给您带来卷发所无法提供的任何功能。
Stijn de Witt

3
@Nocturno我认为您的开幕词有点误导。There's nothing stopping malicious code from spoofing the origin->是的,javascript无法设置Origin。是的,用户可以修改其浏览器/使用提琴手来更改原点,但这并不是CORS的防御目标。攻击者控制的网站无法更改Origin,这很重要。
RJFalconer

12

总结一下:

问:相同来源策略(SOP)仅由浏览器执行吗?
答:是的。对于您在浏览器中进行的所有呼叫,SOP肯定是由浏览器应用的。服务器可能会或可能不会检查请求的来源。

问:如果请求不符合SOP,浏览器是否会阻止它?
答:不,这超出了浏览器的权限。浏览器只是发送跨源请求,然后等待响应,以查看服务器是否通过Access-Control-*标头将呼叫合法地发出信号。如果服务器不发送回Access-Control-Allow-Origin标头,不回显调用方的来源或不发送回*标头,则浏览器要做的所有事情就是避免向调用方提供响应。

问:这是否意味着我不能欺骗Origin
答:在浏览器中并使用脚本,您无法覆盖Origin它,因为它处于浏览器的控制之下。但是,如果您想入侵自己,则可以使用安装在计算机上的浏览器扩展或其他工具来篡改从浏览器发出的呼叫。您也可以发出HTTP使用电话curlPythonC#等,并改变Origin头欺骗服务器。

问:因此,如果我可以通过更改来欺骗服务器Origin,这CORS是否不安全?
答: CORS本身对安全性保持沉默-即请求的身份验证和授权。服务器可以根据请求使用的任何机制(例如Cookie和标头)来检查请求并进行身份验证/授权,这取决于服务器。话虽如此,它可以在发生XSS之类的攻击时为我们提供更多保护:

示例: 假设您已经登录到网站,并且恶意脚本试图向银行网站发送请求以查询余额:Reflected XSS攻击。您的银行网站信任来自(代表此处)网站的凭据,因此请求得到身份验证,并发出HTTP针对恶意代码的响应。如果您的银行网站不关心与其他来源共享其端点,则不包括Access-Control-Allow-Origin响应中的标头。现在,在请求到达时,浏览器意识到该请求是Cross Origins请求,但是响应并不表明服务器愿意与您的网站共享资源(此处为余额查询端点)。因此,它破坏了流程,因此返回的结果将永远不会到达恶意代码。


不错,比接受的答案更好/更清晰IMO
3dGrabber
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.