CSRF 是不是可以使用 PUT 或 DELETE 方法?

Posted

技术标签:

【中文标题】CSRF 是不是可以使用 PUT 或 DELETE 方法?【英文标题】:Is CSRF possible with PUT or DELETE methods?CSRF 是否可以使用 PUT 或 DELETE 方法? 【发布时间】:2012-08-03 16:56:59 【问题描述】:

CSRF 是否可以使用 PUT 或 DELETE 方法?还是使用 PUT 或 DELETE 会阻止 CSRF?

【问题讨论】:

【参考方案1】:

好问题!

在一个完美的世界里,我想不出一种方法来执行 CSRF 攻击。

您不能使用 html 表单发出 PUT 或 DELETE 请求。 图像、脚本标签、CSS 链接等都向服务器发送 GET 请求。 XmlHttpRequest 和 Flash/Silverlight/Applets 等浏览器插件会阻止跨域请求。

因此,一般来说,对支持 PUT/DELETE 动词的资源进行 CSRF 攻击是不可能的。

也就是说,世界并不完美。可能有几种方法可以使这种攻击成为可能:

    Rails 等 Web 框架支持“伪方法”。如果您放置一个名为_method 的隐藏字段,将其值设置为PUT 或DELETE,然后提交GET 或POST 请求,它将覆盖HTTP Verb。这是一种从浏览器表单支持 PUT 或 DELETE 的方法。如果您正在使用这样的框架,您将不得不使用标准技术保护自己免受 CSRF 的影响

    您可能不小心在服务器上为 CORS 设置了宽松的响应标头。这将允许任意网站发出 PUT 和 DELETE 请求。

    在某些时候,HTML5 计划在 HTML 表单中包含对 PUT 和 DELETE 的支持。但后来,他们取消了这种支持。不能保证以后不会添加。一些浏览器可能实际上支持这些动词,这可能对你不利。

    可能只是某些浏览器插件中存在一个错误,可能允许攻击者发出 PUT/DELETE 请求。

简而言之,我建议保护您的资源,即使它们仅支持 PUT 和 DELETE 方法。

【讨论】:

很好的答案,尽管浏览器中没有任何东西会“阻止”跨域请求。 I've answered too 对此有更多了解。 说到不完美的世界,当前版本的 Internet Explorer 11 允许使用 DELETE 方法将 XMLHttpRequests 发送到其他来源。【参考方案2】:

没有。依赖 HTTP 动词不是防止 CSRF 攻击的方法。这完全取决于您的网站是如何创建的。您可以将 PUT 用作 POST,将 DELETE 用作 GET - 这并不重要。

为防止 CSRF,请采取here 概述的一些步骤:

网站有各种可用的 CSRF 对策:

在所有表单提交和副作用 URL 中要求一个秘密的、用户特定的令牌会阻止 CSRF;攻击者的站点无法放置 提交中的正确令牌1 要求客户端在用于执行任何安全操作的同一 HTTP 请求中提供身份验证数据 影响(汇款等) 限制会话 cookie 的生命周期检查 HTTP Referer 标头或(和) 检查 HTTP Origin 标头[16] 确保没有 clientaccesspolicy.xml 文件授予对 Silverlight 控件的意外访问权限[17] 确保没有 crossdomain.xml 文件授予对 Flash 电影的意外访问权限[18] 验证请求的标头是否包含 X-Requested-With。由 Ruby on Rails(v2.0 之前)和 Django(v1.2.5 之前)使用。 这种保护已被证明是不安全的 [19] 在以下组合下 浏览器插件和重定向可以让攻击者 在对任何网站的请求中提供自定义 HTTP 标头,因此 允许伪造请求。

【讨论】:

谢谢,我听说了这个解决方案; 1)如何用PUT进行csrf攻击? 2)您的一些基于标头的解决方案 - 这是您非常依赖浏览器限制并且它可以工作,除了您提到的旧闪存错误......【参考方案3】:

是的,CSRF 可以通过 PUT 和 DELETE 方法实现的,但只能在使用非限制性策略启用 CORS 的情况下。

我不同意Sripathi Krishnan's answer:

XmlHttpRequest 和 Flash/Silverlight/Applets 等浏览器插件 将阻止跨域请求

没有什么能阻止浏览器发出跨域请求。 Same Origin Policy 确实 not 阻止 a request 被发出 - 它所做的只是阻止浏览器读取请求。

如果服务器没有选择CORS,这将导致发出预检请求。这是阻止使用 PUT 或 DELETE 的机制,因为它不是一个简单的请求(方法需要是 HEAD、GET 或 POST)。当然,假设有一个正确锁定的 CORS 策略(或者根本没有,默认情况下是安全的)。

【讨论】:

我想知道为什么这个答案只在这里!这是非常重要的一点!【参考方案4】:

理论上它应该是不可能的,因为没有办法发起跨域 PUT 或 DELETE 请求(CORS 除外,但这需要预检请求,因此需要目标站点的合作)。在实践中,我不会依赖这一点 - 许多系统已经被例如咬伤了。假设 CSRF 文件上传攻击是不可能的(不应该,但某些浏览器错误使其成为可能)。

【讨论】:

但是浏览器/插件的错误也阻止了使用 HTTP 标头(referer 或自定义标头)的 csrf 防御,为什么不将这种简单的技术用于小型网站? 这就是为什么你不应该使用引用者来防御 CSRF。使用令牌是可靠的,无论如何你都需要这样做(除非你根本不使用 POST,这对可访问性来说不是很好)。【参考方案5】:

CSRF 确实可以使用 PUT 和 DELETE,具体取决于服务器的配置。

考虑 CSRF 的最简单方法是考虑在您的浏览器中打开两个选项卡,一个在您的用户经过身份验证的情况下向您的应用程序打开,另一个选项卡向恶意网站打开。

如果恶意网站向您的应用程序发出 javascript 请求,浏览器将随请求发送标准 cookie,从而允许恶意网站使用已经过身份验证的会话“伪造”请求。该网站可以执行任何类型的请求,包括 GET、PUT、POST、DELETE 等。

防御CSFR的标准方法是发送一些恶意网站无法知道的请求。这可以像其中一个 cookie 的内容一样简单。虽然来自恶意站点的请求会随其发送 cookie,但它实际上无法访问 cookie,因为它由不同的域提供服务,并且浏览器安全性阻止它访问另一个域的 cookie。

将 cookie 内容称为“令牌”。您可以将令牌与请求一起发送,并在服务器上确保在继续请求之前已正确提供了“令牌”。

下一个问题是如何通过所有不同的请求发送该值,删除特别困难,因为它不是为具有任何类型的有效负载而设计的。在我看来,最简洁的方法是使用令牌指定请求标头。像这样的东西 x-security-token = token.这样,您可以查看传入请求的标头,并拒绝任何缺少令牌的请求。

过去,标准的 ajax 安全性限制了可以通过 ajax 在恶意服务器上执行的操作,但是,现在,该漏洞取决于您如何设置服务器的访问控制配置。有些人打开他们的服务器是为了更容易进行跨域调用或让用户创建自己的 RESTful 客户端等,但这也使得恶意站点更容易利用,除非上面的 CSRF 预防方法是到位。

【讨论】:

我的网站是“单一来源”。所以我不允许 PUT 或 DELETE 从其他来源。 "如果恶意网站向您的应用程序发出 javascript 请求,浏览器将随请求发送标准 cookie" - 情况并非如此:浏览器不应在跨域请求中发送 cookie除非接收站点特别允许。

以上是关于CSRF 是不是可以使用 PUT 或 DELETE 方法?的主要内容,如果未能解决你的问题,请参考以下文章

Django-csrf中间件

使用Ajax (put delete ) django原生CBV 出现csrf token解决办法

“detail”:“CSRF 失败:CSRF 令牌丢失或不正确。”

csrf防护处理

保护csrf Nodejs表单

PUT 和 DELETE HTTP 请求方法有啥用处?