Rails:csrf_meta_tag 是如何工作的?

Posted

技术标签:

【中文标题】Rails:csrf_meta_tag 是如何工作的?【英文标题】:Rails: How Does csrf_meta_tag Work? 【发布时间】:2012-04-17 07:23:19 【问题描述】:

我是一名 php 开发人员,通过阅读 Michael Hartl's tutorial 学习 Ruby on Rails。这是书中的一段话,指的是csrf_meta_tag

...Rails 方法csrf_meta_tag [防止] 跨站请求 伪造(CSRF),一种恶意网络攻击。不要担心 细节(我不知道);只知道 Rails 正在努力保持你的 应用程序安全。

问题是,我真的很好奇。插入csrf-paramcsrf-token 元标记如何防止CSRF?我尝试了谷歌搜索,但找不到任何东西。

【问题讨论】:

@MikhailNikalyukin 谢谢(我认为)。这解释了 CSRF,我已经知道了它的基础知识,但它没有解释 元标记(相对于隐藏的表单字段)如何防止它。你知道答案吗? 【参考方案1】:

csrf_meta_tag 基本上实现了与隐藏表单字段相同的功能,但它可以为未绑定到表单的 javascript 请求提供一种获取令牌的简单方法。

如果您使用 jquery-ujs 库,则该元标记的内容会自动添加(作为请求标头)到发出的任何 ajax 请求中。

【讨论】:

又短又甜。你回答了我的问题。谢谢! 刚刚完成:this article 提到 ujs 也可以使用它们来更新过时的片段缓存。 Relevant uJS source line。以防万一有像我这样的新手想知道:form_tag 和其他助手也将 CSRF 令牌添加到表单中,因此它们可以在没有 Js 的情况下工作。【参考方案2】:

csrf_meta_tag 将本质上是数字签名的内容插入页面,作为验证进入应用程序服务器的请求实际上来自正确登录的用户。这有助于防止跨站点脚本(当您在另一个选项卡中登录到 GMail 时,完全不相关页面上的脚本会触发 GMail 请求)。

我想澄清一下,csrf_meta_tag 本身并不能阻止不相关的页面向您的 GMail(或作为攻击目标的任何其他服务)发出请求,但 @ 中的“数字签名” 987654324@ 用于验证所述请求的有效性。无效请求(即来自跨站点脚本尝试)应该无法通过验证,因此会被丢弃。

换一种说法,从攻击者的角度来看:

csrf_meta_tags 存在之前(它们绝不是 Rails 独有的),成功的跨站点脚本攻击允许恶意站点以一种使请求看起来好像是代表用户完成。因此,假设您是 Web 服务的管理员,并且在一个浏览器选项卡中您已登录到该服务的管理面板。如果在另一个选项卡中打开的恶意站点针对您的服务进行攻击,则该恶意站点可能能够运行发出管理员请求的脚本,例如从数据库中转储用户列表、窃取其他敏感数据,或潜在地损害、破坏、或破坏服务中包含的数据,同时(从服务器的角度来看)都是来自管理员本身的有效请求。 csrf_meta_tag 是一种签署请求的方式,有助于阻止此类尝试成功。

有更详细的解释available here。

在你的 Rails 生成的页面上做一个“查看源代码”也很有教育意义,你会看到 CSRF 标记的样子。

【讨论】:

感谢您的详细解答!尽管它很有帮助并且我能够从中学习,但它并没有解释 元标记 如何帮助预防 CSRF(与隐藏表单字段相反)。但我真的很感激你的时间。再次感谢!【参考方案3】:

在 Rails 中它会这样工作

def csrf_meta_tags
    if protect_against_forgery?
      [
        tag('meta', :name => 'csrf-param', :content => request_forgery_protection_token),
        tag('meta', :name => 'csrf-token', :content => form_authenticity_token)
      ].join("\n").html_safe
    end
  end

See more details just click

您还需要查看Ruby On Rails Security Guide

这里是不错的blog

但是 - 我更喜欢国家漏洞数据库,这是很好的解释

CWE-352: Cross-Site Request Forgery (CSRF)

CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Check this document for CWE - Common Weakness Enumeration

【讨论】:

漏洞数据库的好链接! 感谢您的详细解答!尽管它很有帮助并且我能够从中学习,但它并没有解释 元标记 如何帮助预防 CSRF(与隐藏表单字段相反)。不过,指向源代码的链接对此进行了一些解释。无论如何,我真的很感谢你的时间。再次感谢! 嗨尼克,我有问题的方向,我会很快改变我的答案并更新你。主要是在这个周末。【参考方案4】:

csrf_meta_tags 指示 ajax 请求将这些请求用作向服务器发出请求的表单参数之一。 Rails 期望 csrf 作为表单主体(参数)的一部分来处理您的请求。使用这些元标记,您可以构建表单正文或 csrf 标头以满足您的需求。我希望这个答案对您的问题有所帮助。

【讨论】:

【参考方案5】:

助手csrf_meta_tags的输出:

<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="J/gw2ePXHS9Z1SUSSeUQgMmPhsPEFlFbMrLTLFHLfKjeWh7g4uyOnBlfKnlZlmCBiALDWdDWCSo1z0tybGVtfA==" />

此令牌可以包含在 ajax 请求中。 示例(jquery-ujs):

https://github.com/rails/jquery-ujs/blob/4b6e30f68ff1244fc0c790641d3408c2695a29bd/src/rails.js#L70

    csrfToken: function() 
     return $('meta[name=csrf-token]').attr('content');
    ,

    // URL param that must contain the CSRF token
    csrfParam: function() 
     return $('meta[name=csrf-param]').attr('content');
    ,

    // Make sure that every Ajax request sends the CSRF token
    CSRFProtection: function(xhr) 
      var token = rails.csrfToken();
      if (token) xhr.setRequestHeader('X-CSRF-Token', token);
    ,

【讨论】:

以上是关于Rails:csrf_meta_tag 是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3 - 关联 - 它是如何工作的?

Rails:后台文件上传如何工作?

Rails - 格式和渲染 - 它们是如何工作的?

Rails:respond_to 块是如何工作的?

你如何让 JQuery 与 Rails 6 和 Webpacker 6 一起工作

Ruby on Rails 中的会话如何工作?