【问题标题】:What's to stop malicious code from spoofing the "Origin" header to exploit CORS?如何阻止恶意代码欺骗“Origin”标头来利用 CORS?
【发布时间】:2014-01-30 05:52:21
【问题描述】:

按照我的理解,如果在 foo.com 的页面上运行的客户端脚本想要从 bar.com 请求数据,则在请求中它必须指定标头 Origin: http://foo.com,并且 bar 必须以 @ 响应987654327@.

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

【问题讨论】:

  • 我认为关键在于提供页面的原始域(此处为foo.com)必须提供Access-Control-Allow-Origin 标头,否则浏览器不允许对@987654331 的请求@.
  • 通读this post确实帮助我理解了浏览器、源服务器和目标服务器之间的cors过程。 html5rocks.com/en/tutorials/cors
  • @ChrisHayes 这根本不是 CORS 的工作方式。您可以通过查看the specthis great MDN wiki page on the subject 了解更多信息。
  • @brendonparker 是的,这是一篇很棒的文章。那位作者回答了很多关于 SO 的 CORS 问题,并且还维护了enable-cors.org
  • @RayNicholus 有趣的是,我显然离题了。感谢您的链接。从对我的评论的投票来看,我并不是唯一一个遭受这种错觉的人。我希望这两个人回来学习(并删除他们的选票!)。

标签: javascript ajax http cors


【解决方案1】:

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

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

【讨论】:

  • 这很有意义。如果浏览器不允许 JavaScript 覆盖 Origin 标头,则没有问题。如果您从浏览器外部执行请求,您将不会拥有 cookie。我想我很困惑,因为在我阅读的所有文档中,都没有明确说明 Origin 标头无法被覆盖。谢谢!
  • 如果有人想欺骗某些东西,那么他们可以这样做。他们可以使用几乎任何脚本语言来构建 http 请求。 Perl 和 Python 有 http 库,这使得这很容易。库存储和发送 cookie,允许您添加任意标头,并提供大量调试信息。因此,当您在浏览器中同时登录时,CORS 标头只是为了让您阅读的论坛上的恶意 javascript 更难对您在另一个域上的银行帐户做一些讨厌的事情。
  • 为了澄清一下,恶意用户可以简单地生成一个浏览器实例,该实例经过修补以允许他们手动控制 Origin 标头,然后完美地模拟普通用户、cookie、AJAX 等。
  • "浏览器可以控制 Origin 标头的设置,用户不能覆盖这个值。"我敢肯定,一旦请求离开浏览器,使用像 Fiddler2 或 Charles 这样的工具来修改标头非常容易。
  • 恶意用户可以简单地生成一个浏览器实例,该实例已被修补以允许他们手动控制 Origin 标头如果您可以访问机器到可以“只需生成一个修补过的浏览器实例'(对我来说实际上听起来并不那么简单),为什么不直接从磁盘读取 cookie?它们以您知道的纯文本形式存储。在现实生活中,跨站点脚本是一种真正的威胁,而您的攻击场景只是人为且不切实际。
【解决方案2】:

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


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

我发现的第一件事是Origin 标头是一个HTTP forbidden header name,不能以编程方式修改。这意味着您可以使用 Modify Headers for Google Chrome 在大约 8 秒内对其进行修改。

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

然后我欺骗了客户端 2 的 Origin 标头以匹配客户端 1。服务器收到欺骗的Origin 标头,并成功通过了白名单检查(如果您是半空玻璃的人,则失败)。在那之后,服务器尽职尽责地消耗它设计消耗的所有资源(数据库调用、发送昂贵的电子邮件、发送更昂贵的短信等)。完成后,服务器会愉快地将欺骗的 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 并正确拒绝了响应。 此时无所谓,因为服务器已经接受了欺骗性请求并花了我的钱。

【讨论】:

  • @Nocturno,谢谢你的例子。让我补充一下我的观察。 CORS 与浏览器安全功能有关。如果安全浏览器从其原始状态进行修改,则可能会被解释为该浏览器可能缺少安全功能。
  • 一点也不出色。它完全忽略了 CORS 的意义。如果您能够拦截来自用户机器的请求,您只需读取他们的 cookie、安装键盘记录程序、病毒和所有其他真正的威胁。 CORS 用于保护登录到站点 A 的诚实用户免受恶意脚本的影响,该脚本以某种方式注入站点 B。站点 B 上的脚本(可能是论坛帖子中的 Javascript 的 sn-p,站点 B 未正确转义) 在用户帐户下的站点 A 上执行操作(例如删除内容等),使用站点 A 的会话 cookie。
  • 这称为跨站点脚本,无需 CORS 即可完成,而无需获得对用户机器的控制权。这就是重点。不需要控制用户的机器,因为当向站点 A 发出请求时,浏览器会自动将会话 cookie 添加到请求中,因此它看起来像是来自用户本身的有效请求,而实际上它来自其他一些脚本地点。同源策略阻止它,CORS 用于将应该被授予访问权限的域列入白名单,即使它们位于不同的来源。
  • @Nocturno 是的,我可能有点太粗鲁了,对此感到抱歉。你原来的观点是站得住脚的。同源策略是一种浏览器安全功能,CORS 是一种通过将某些域列入白名单来削弱该安全性的机制。 OP 需要了解欺骗 Origin 标头作为“攻击”并不真正可行,因为它不会为您带来任何无法获得的东西,例如卷曲。
  • @Nocturno 我认为您的开场白有点误导。 There's nothing stopping malicious code from spoofing the origin -> 是的,javascript 无法设置 Origin。是的,用户可以修改他们的浏览器/使用提琴手来改变来源,但这不是 CORS 所要防御的; 攻击者控制的网站不能改变 Origin,这才是最重要的。
【解决方案3】:

简单总结一下:

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

问:如果请求不符合 SOP,浏览器会阻止它吗?
答:不,它超出了浏览器的权限。浏览器只需发送跨源请求并等待响应,以查看服务器是否通过 Access-Control-* 标头发出合法的调用信号。如果服务器没有发回Access-Control-Allow-Origin标头,没有回显调用者的来源,或者没有在标头中发回*,那么浏览器将做的所有事情就是避免提供响应调用者。

问:这是否意味着我不能欺骗 Origin
答: 在浏览器和使用脚本时,您不能覆盖 Origin,因为它在浏览器的控制。但是,如果您想破解自己,您可以使用浏览器扩展程序或您安装在计算机上的其他工具来篡改来自浏览器的呼叫。您还可以使用curlPythonC# 等发出HTTP 调用,并更改Origin 标头以欺骗服务器。

问:如果我可以通过更改 Origin 来欺骗服务器,这是否意味着 CORS 不安全?
答: CORS per se 对安全性保持沉默——即请求的身份验证和授权。由服务器检查请求并通过它们使用的任何机制(例如 cookie 和标头)对其进行身份验证/授权。话虽如此,它可以在 XSS 等攻击的情况下为我们提供更多保护:

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

【讨论】:

    【解决方案4】:

    这个话题有点老了,但绝对有帮助,我会为任何想知道是否有任何方法可以防止攻击者欺骗 cors 的人添加以下提示。

    如上所述,没有办法防止 Origin 标头被欺骗。

    但是,例如,如果您要构建一个返回公开显示数据的 API,并希望避免攻击者溢出服务器以检索所有数据,您可以执行以下操作:

    • 阻止全局数据请求(一次返回所有可用数据的查询)
    • 设置记录器,检查恶意用户是否正在编辑或创建脚本以发送多个快速后续请求。您可以结合使用 IP 地址和其他唯一标头来尝试实现这一目标。

    如果您想保护 REST API,HMAC 或 Oauth2 是您的最佳选择(每个都有自己的用途)。

    但是 cors 将始终保持可编辑状态,并且永远不应该用于检查请求发出者的身份。

    【讨论】:

      猜你喜欢
      • 2013-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 2019-08-10
      • 1970-01-01
      • 1970-01-01
      • 2017-01-12
      相关资源
      最近更新 更多