为啥预检 CORS 不阻止 CSRF 攻击?

Posted

技术标签:

【中文标题】为啥预检 CORS 不阻止 CSRF 攻击?【英文标题】:Why doesn't pre-flight CORS block CSRF attacks?为什么预检 CORS 不阻止 CSRF 攻击? 【发布时间】:2017-04-30 02:50:46 【问题描述】:

Everyone 说 CORS 没有做任何事情来防御 CSRF 攻击。这是因为 CORS 会阻止域外访问(读取)您域上的资源,但 不会 阻止处理请求。所以邪恶的网站可以发送改变状态的 DELETE 请求,而不用担心他们不能读回结果。

这一切都很好。

pre-flight CORS 除外。

在这种情况下,CORS 在发送请求之前会查看它,并检查它是否合法。如果不是,则拒绝该请求。

因此,CSRF 攻击者尝试发送的 DELETE 请求未通过飞行前检查,因此被拒绝。 CSRF 攻击失败。

我在这里错过了什么?

【问题讨论】:

【参考方案1】:

飞行前请求通常不会阻止 CSRF。例如,并非所有跨域 ajax 调用都会生成飞行前请求,普通 POST 不会。不过,在某些特定情况下,飞行前请求确实有助于降低风险。

另一个问题与检查引用者/来源相同。虽然攻击者不可能在恶意网站上以纯 javascript 覆盖引荐来源网址或来源,但可以使用合适的浏览器插件(例如旧版本的 Flash)来做到这一点。如果浏览器插件允许这样做,攻击者可能能够在没有预先飞行的情况下发送跨域请求。所以你不想只依赖飞行前的请求。

【讨论】:

"例如,并非所有跨域 ajax 调用都会生成飞行前请求,普通 POST 不会。"为什么不呢? 你不需要ajax来做一个简单的跨域post。您也可以使用普通形式的帖子,因此限制它没有太大价值。 哦。我明白你在说什么。我想知道....为什么 CORS 飞行前会为 PUT 请求而不是 POST 请求激活?就像你说的那样,POST 可能同样危险.... 他们确实可以。如果 GET 更改服务器上的某些内容,即使是 GET 也可能很危险,当然他们不应该这样做,但这可能是无意的。在 php 或经典 ASP 等脚本语言中,很容易编写您打算在 POST 上工作的代码,但也可以与 GET 一起工作,因为获取参数是通用的。在这种情况下,GET 也容易受到 CSRF 的影响,并且跨域 ajax GET 也不会生成预飞行。原因是通过一个简单的链接就可以实现跨域GET。 是的,但 GET 至少预计不会改变状态。而 POST 预计会改变状态。那么为什么飞行前允许 POST 呢???

以上是关于为啥预检 CORS 不阻止 CSRF 攻击?的主要内容,如果未能解决你的问题,请参考以下文章

跨域请求被阻止原因:CORS 预检通道未成功

被 CORS 阻止:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权

是否有可能在 CORS 之前进行 CSRF 攻击?

Google OAuth2:重定向已被 CORS 政策阻止:请求需要预检,不允许遵循跨域重定向

被 CORS 策略阻止:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权

角 POST 请求被 CORS 策略阻止:对预检请求的响应未通过访问控制检查