我理解的方式是,如果一个客户端脚本运行在foo.com的页面上,想要从bar.com请求数据,在请求中它必须指定头文件Origin: http://foo.com,而bar必须响应Access-Control-Allow-Origin: http://foo.com。
有什么可以阻止来自roh.com站点的恶意代码简单地欺骗标题来源:http://foo.com来从酒吧请求页面?
我理解的方式是,如果一个客户端脚本运行在foo.com的页面上,想要从bar.com请求数据,在请求中它必须指定头文件Origin: http://foo.com,而bar必须响应Access-Control-Allow-Origin: http://foo.com。
有什么可以阻止来自roh.com站点的恶意代码简单地欺骗标题来源:http://foo.com来从酒吧请求页面?
浏览器可以控制Origin头的设置,用户不能重写这个值。因此,您不会看到来自浏览器的Origin标头被欺骗。恶意用户可以创建一个curl请求,手动设置Origin报头,但是这个请求将来自浏览器之外,并且可能没有特定于浏览器的信息(例如cookie)。
记住:CORS不是证券。不要依赖CORS来保护您的站点。如果您正在提供受保护的数据,请使用cookie或OAuth令牌或Origin报头以外的其他东西来保护数据。CORS中的Access-Control-Allow-Origin报头只指示应该允许哪些源进行跨源请求。别再依赖它了。
TLDR:没有什么可以阻止恶意代码欺骗源。当这种情况发生时,您的服务器将永远不会知道它,并将对请求采取行动。有时这些请求是昂贵的。所以不要用CORS来代替任何类型的证券。
我最近一直在研究CORS,我也问过自己同样的问题。我发现浏览器可能足够聪明,当它看到一个欺骗的CORS请求时就能知道,但您的服务器没有那么聪明。
我发现的第一件事是Origin头是一个HTTP禁止的头名,不能通过编程方式修改。这意味着你可以修改它在大约8秒使用修改谷歌Chrome头。
为了测试这一点,我设置了两个客户端域和一个服务器域。我在服务器上包含了CORS白名单,它允许来自客户机1的CORS请求,但不允许来自客户机2的CORS请求。我测试了两个客户机,客户机1的CORS请求成功,而客户机2的CORS请求失败。
Then I spoofed Client 2's Origin header to match Client 1's. The Server received the spoofed Origin header, and successfully passed the whitelist check (or failed if you're a glass-half-empty kind of guy). After that, the Server performed dutifully by consuming all the resources that it was designed to consume (database calls, sending expensive emails, sending even more expensive sms messages, etc.). When that was done, the server happily sent the spoofed Access-Control-Allow-Origin header back to the browser.
我读过的文档指出,接收到的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,并正确地拒绝响应。这一点并不重要,因为服务器已经接受了欺骗请求并花了我的钱。
简单总结一下:
Q:同源策略(SOP)是否只在浏览器上执行? 是的。对于在浏览器内进行的所有调用,该SOP肯定是由浏览器应用的。服务器可能检查请求的来源,也可能不检查。
Q:如果一个请求不符合SOP,浏览器会阻止它吗? A:不,这超出了浏览器的权限。浏览器只是发送跨源请求,并等待响应,以查看服务器通过Access-Control-*报头是否表示调用是合法的。如果服务器没有返回Access-Control-Allow-Origin头,没有回显调用者的原点,或者没有在头中返回*,那么浏览器所要做的就是避免向调用者提供响应。
Q:这是否意味着我不能恶搞《起源》? 答:在浏览器和使用脚本,你不能覆盖起源,因为它是在浏览器的控制。然而,如果你想入侵自己,你可以使用浏览器扩展或其他你安装在你的机器上的工具来篡改从你的浏览器发出的呼叫。您还可以使用curl、Python、c#等发出HTTP调用,并更改Origin报头来欺骗服务器。
问:如果我可以通过修改Origin来欺骗服务器,这是否意味着CORS不安全? 答:CORS本身对安全性(即请求的身份验证和授权)保持沉默。由服务器来检查请求,并通过它们使用的任何机制(如cookie和报头)对其进行身份验证/授权。话虽如此,在遇到XSS这样的攻击时,它可以保护我们更多:
Example: Let's say you've logged in to your website and a malicious script attempts to send a request to your bank website to inquire your balance: a Reflected XSS attack. Your bank website trusts the credentials coming from (here on behalf of) your website so the request gets authenticated and a HTTP response aiming for the malicious code gets issued. If your bank website doesn't care about sharing its endpoints with other origins, it doesn't include Access-Control-Allow-Origin header in the response. Now, upon arrival of the request, the browser realizes that the request was a Cross Origins request, but the response doesn't show that the server was happy to share the resource (here the balance query endpoint) with your website. So it breaks the flow, hence the returned result will never reach to the malicious code.
这个话题有点老了,但肯定有帮助,我将为那些想知道是否有办法防止攻击者欺骗cors的人添加以下提示。
如上所述,没有办法防止Origin头被欺骗。
然而,如果你正在构建一个API,返回公开显示的数据,并希望避免攻击者溢出服务器来检索所有数据,你可以执行以下操作:
防止全局数据请求(一次返回所有可用数据的查询) 设置一个记录器,检查恶意用户是否正在编辑或创建脚本以发送多个快速后续请求。您可以使用IP地址和其他唯一头的组合来尝试实现这一点。
如果您想保护一个rest API, HMAC或Oauth2是最好的选择(每个都有自己的目的)。
但是cors始终是可编辑的,永远不应该用来检查请求发送者的身份。
虽然恶意网站可能会欺骗请求中的Origin报头,以欺骗服务器允许CORS,但服务器可以通过一些方法来防止这种情况。
一种方法是使用一种称为“源白名单”的技术,其中服务器只允许来自特定的、可信的源的请求。这意味着即使恶意网站欺骗了Origin头,服务器也不会允许该请求,除非该源在白名单上。
另一种方法是使用签名令牌或cookie来验证请求。在这种情况下,服务器可以通过检查签名或cookie值来验证请求是否来自可信源。这使得恶意网站更难以欺骗服务器允许CORS。
同样值得注意的是,CORS只是防止跨站点请求的一层安全措施。web开发人员还可以使用其他技术和措施来进一步保护他们的网站免受恶意请求的侵害。