【问题标题】:Does a proper CORS setup prevent CSRF attack?正确的 CORS 设置是否可以防止 CSRF 攻击?
【发布时间】:2013-11-16 14:30:52
【问题描述】:

如果在服务器上正确设置了 CORS,只允许特定来源访问服务器,

这足以防止 CSRF 攻击吗?

【问题讨论】:

标签: cors csrf same-origin-policy websecurity


【解决方案1】:

正确的 CORS 设置

现代浏览器试图通过一种安全机制又名 SOP(同源策略)来防止 跨域请求伪造攻击

CORS 设置将打开 SOP 的一些限制并放宽这些限制。

我会将正确的 CORS 设置解释为:

  • 具有 SOP 功能的浏览器
  • 允许 cors 标头不是 *<request-origin-host>(只是受信任的主机)

SOP 限制

如果任何页面请求跨域,有3个策略:

  1. 写请求,例如:链接、重定向、xhr、表单提交(允许)(规则 1)
  2. 嵌入请求如:<script>, <link>, <img>, <video>, <audio>, <object>, <embed>, @font-face, <iframe>(允许)(规则 2)
  3. 读取请求(禁止)(规则 3)

在上述第一个选项(写请求)中,可能会因跨站点请求伪造而被滥用。

The SOP mechanism just ALLOWED these write requests

为什么?

  • 为了向后兼容现有网站
  • 方便的开发和使用(想想如果存在复杂的重定向解决方案会发生什么!!!)

浏览器 SOP 对此步骤的唯一帮助是为资源更改(POST/PUT/...)XHR 请求发送飞行前请求

注意:在以后的步骤中,它的帮助远不止这些

在pre-flight请求中,服务器发送CORS Allow Header,浏览器判断是否允许更改资源请求。

例如:如果有一个带有post方法的表单更改服务器上的资源,CORS Allowance Header将从服务器接收,但服务器上的资源已经更改。 (索拉布死后的解药)

SOP 将防止 CSRF 攻击 xhr 请求而不是 application/x-www-form-urlencoded 请求

  • evil.com 上可以有一个表单,或者脚本可以在 DOM 中附加一个表单并自动发送该表单。

或者它自己的 xhr 预检可能不会像我们预期的那样阻止,因为:

  • 在某些浏览器中,它可能会因为性能问题而被禁用(没有 2 个请求)
  • 如果未设置 Origin 标头
  • 服务器可能允许*
  • 预检请求中的一些错误会暴露功能...

CSRF-令牌机制

CSRF 令牌可用于表单和 xhr 请求。

CSRF-token 机制可以防止 CSRF 攻击,前提是 CSRF Token 不暴露于跨域恶意脚本

但可以想象这种情况:恶意网站上的脚本:

  • 首次请求表单(即编辑表单或删除表单)并获取令牌
  • 然后使用 application/x-www-form-urlencoded 或 xhr 发送令牌

SOP 支持 CSRF-token

我已经提到过 SOP 限制了读取请求。 并且只允许嵌入的读取请求。

因此 SOP 将防止 CSRF 令牌被恶意脚本暴露(获取表单并使用令牌创建虚假表单):

  • 正确的 CORS 设置
  • 表单无法嵌入

TL;DR

SOP 机制(使用规则 #1)(正确的 CORS 设置)只能防止 CSRF xhr(在实现中可能存在一些缺陷)(不能保护所有场景)

如果令牌没有被泄露,CSRF-Token 可以保护 CSRF 攻击

SOP 机制(规则#3)可以保护 CSRF-token & CSRF-token 保护用户免受 CSRF-attack

我们应该注意不要使用嵌入式资源规则(规则#2)破坏 CSRF-token。 (主要是 iframe 滥用)

MDN如何阻止跨域访问

  • 为防止跨域写入,请检查请求中不可猜测的令牌 — 称为跨站点请求伪造 (CSRF) 令牌。你必须 防止跨域读取需要此令牌的页面。
  • 为防止资源的跨域读取,请确保该资源不可嵌入。通常有必要防止嵌入,因为 嵌入资源总是会泄露一些关于它的信息。
  • 为防止跨域嵌入,请确保您的资源不能被解释为上面列出的可嵌入格式之一。浏览器 可能不尊重 Content-Type 标头。例如,如果您指向一个
HTML 文档中的标签,浏览器将尝试解析 HTML 作为 JavaScript。当您的资源不是您的入口点时 站点,您还可以使用 CSRF 令牌来防止嵌入。

进一步阅读

Same Origin Policy

CSRF Token mechanisms (implementation in The Laravel)

【讨论】:

    【解决方案2】:

    更具体地说,很容易错误地认为如果 evil.com 由于 CORS 无法向 good.com 发出请求,那么 CSRF 就会被阻止。然而,有两个问题被忽略了:

    1. CORS 仅受浏览器支持。这意味着谷歌浏览器将遵守 CORS,并且不会让 evil.com 向 good.com 提出请求。但是,想象一下有人构建了一个原生应用程序或任何具有将内容发布到您的站点的表单。 XSRF 令牌是防止这种情况的唯一方法。

    2. 是否容易忽略CORS仅用于JS请求的事实。 evil.com 上的常规表单回传到 good.com,尽管使用了 CORS。

    由于这些原因,CORS 不是 XSRF 令牌的良好替代品。最好同时使用。

    【讨论】:

    • 如果我没记错的话,你的第一点可能是无效的——因为 CSRF 攻击只适用于浏览器。
    • @ineedahero 提到 #1 不适用于此处。对于#2,您不能在表单帖子上设置虚假的 Origin 标头,因此如果 Origin 存在并且它在您的白名单上,则似乎不可能使用 CSRF。
    • #2 确实适用。 CORS 仅阻止浏览器发出 XHR 请求。如果站点更改了位置 URL(例如,本机表单 POST 或 GET 链接),则 CORS 不适用。
    • 是的,对不起。我本来可以更清楚的。我在上述评论中对@Benja 的说法提出异议。我同意你的回答@aleemb
    • 我明白了,您说得对,请求仍然会被发送。但我的意思是,如果您使用 Origin 标头列入白名单,那么这些情况(表单提交或导航)将被停止,因为它们不会发送 Origin 标头,这比实现 XSRF 令牌要简单得多。跨度>
    【解决方案3】:

    也许

    伙计,这是一项艰巨的任务,而且比其他人提供的要复杂得多。所以“也许”

    首先,CORS 旨在“放松”同源策略,这是防止特定类型 CSRF 攻击的默认设置。但是,同源并不适用于所有类型的请求。

    因此,会话需要超时的时间越长,用户在不受信任的站点上浏览的次数越多,出现 CSRF 攻击的风险就越高。任何触发外部资源请求的标签都可用于执行隐藏的 CSRF 攻击——包括图像、链接标签、一些元标签、嵌入和对象标签等。加载背景图像或类似的。如果您将应用程序标记的标题中的 DTD 文件替换为服务器上的资源,您甚至可以检查您的站点是否已被某人验证——这也是 CSRF。 source

    举个例子,看看这个..

    <img src=victim.bank/check.png?account=...>;从易受攻击的银行站点获取支票照片,而无需生成原始标头或预检请求。 [...] 将显示照片,攻击者可以使用 Javascript 获取照片数据并将其发回。 source

    但是,至少有一个消息来源表明,未来 Web 服务器可能会在图像上返回带有 Access-Control-Allow-Origin (CORS) 标头的图像,这将阻止浏览器呈现图像。这将防止此类 CSRF-GET 攻击..

    如果浏览器检查响应中的 Access-Control-Allow-Origin 标头并拒绝显示,这将是一种有效的防御。 source

    【讨论】:

    • “攻击者可以使用 Javascript 获取照片数据并将其发回”——事实并非如此
    • 当我run that code,在用不同来源的图像替换 URL 后,浏览器控制台说:Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. 所以,不,这是不可能的,因为同源策略启动.
    • @Quentin 查看您的网络选项卡,它并没有阻止发出请求,它只是阻止您访问数据,但如果请求修改了数据,则不会阻止修改发生.这应该仍然是安全的,因为 GET 请求不应该修改数据。
    【解决方案4】:

    实际上,CORS 确实有助于安全性。 CORS 对不同主机之间的 XSS 和 CSRF 攻击有很大帮助。如果一个网站存在 XSS 漏洞并且攻击者想要使用它通过xmlhttprequest 向另一个网页发送恶意请求,由于 CORS,他将无法做到。

    【讨论】:

    • CORS 在这里不提供任何额外的安全性。在 CORS 规范之前,相同的 xhr 发起的请求会被浏览器直接拒绝。
    【解决方案5】:

    不!

    CORS 支持在两个域之间共享,其中 XSRF 所攻击的方法无论如何都不依赖于 CORS。

    我不明白“CORS 已正确设置”是什么意思,但是当使用 XSRF 进行攻击时,浏览器不会要求服务器上的 CORS 标头。

    CORS 不安全 :)

    【讨论】:

    • 应该用粗体大写:“CORS 不安全!” CORS 仅指定服务器允许哪些类型的跨域请求。它不应替代良好的安全实践。
    • 谢谢!我实际上是在笼统地说,您的回答很棒。不过还是谢谢你更新:)
    • 我想我想要得到的是任何人都可以欺骗原始标题吗?如果是这样,CORS 或 Same-Origin-Policy 不会崩溃吗?
    • @programmerdave 被黑或受损的浏览器可能会导致这种情况。 CORS 背后的理念依赖于用户浏览器的可信度。
    • 答案没有说明原因或方式,XSRF/CSRF 是代表用户提出非法请求。例如siteA 调用siteB/logout。严格的 CORS 策略阻止了跨站点 JS 调用,那怎么会呢。
    【解决方案6】:

    没有。

    同源策略(CORS 允许您选择性地打孔)可防止第三方网站伪装成用户以读取(私人)来自其他网站的数据。

    跨站点请求伪造攻击是指第三方站点伪装成用户提交数据到另一个站点(作为该用户)。它不需要读回响应。

    【讨论】:

    • 但它可以,对吧? CSRF-get 例如 victim.bank/check.png?account=...> 从易受攻击的银行站点获取支票照片,而不生成原始标头或预检请求。 [...] 将显示照片,攻击者可以使用 Javascript 获取照片数据并将其发回。 source,
    • 您认为 CSRF 攻击仅限于“提交”数据的假设似乎是错误的。此外,CSRF 无法纠正这种情况也是错误的(尽管即使是现代浏览器也是 ymmv),如果浏览器检查响应中的 Access-Control-Allow-Origin 标头并拒绝显示它,它将是一种有效的防御。(同一来源)
    • @EvanCarroll — 回应您的第一条评论:使用这样的图像可能会触发 CSRF 攻击。由于此答案中描述的原因,CORS 无法阻止这种情况。攻击者可以向用户显示图像(这可能在网络钓鱼攻击中很有用),但他们不能让浏览器将图像的副本(或从图像中提取的数据)发送给攻击者(因为同源策略阻止了它) .您的来源有误。
    • @EvanCarroll — 回复您的第二条评论:通过将数据嵌入到通过图像标签加载的 URL 的查询字符串中提交给服务器的数据仍然被提交。 “如果浏览器检查 Access-Control-Allow-Origin 标头”——没有浏览器会这样做,因此它与关于创作网站的讨论无关。 “这将是一种有效的防御”——同源策略已经是一种有效的防御,可以防止其他网站发现用户可以访问服务器上的哪些图像的信息。
    • 不错的答案,但我认为“相同站点策略”除了“防止伪装阅读”之外还有更多工作要做。它还可以防止 PUT 和 DELETE 动词。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-20
    • 2021-01-30
    • 1970-01-01
    • 2010-11-27
    • 1970-01-01
    • 2019-12-11
    • 2018-01-08
    相关资源
    最近更新 更多