【问题标题】:Is this csrf failure expected?这是预期的 csrf 失败吗?
【发布时间】:2018-06-22 12:55:46
【问题描述】:

鉴于以下一系列事件

  1. 匿名用户打开主页,其中包含一个表单(带有有效的 csrf 令牌)
  2. 用户打开辅助选项卡并登录。
  3. 用户返回原始选项卡并提交表单。

是否预期会导致 csrf 失败,如果是,是否有任何解决方案可以为用户提供更好的体验?

【问题讨论】:

  • 简而言之,这是意料之中的(因为登录时令牌会更改),我想不出避免csrf失败的直接方法。希望有人能给你一个更好的答案。

标签: python django django-csrf


【解决方案1】:

是的,这是安全系统的一部分。鉴于属于匿名用户的 CSRF 令牌可能由攻击者生成/获取(因为他们也是匿名用户),在用户登录后使用该令牌绝对不是一个明智的主意。Django documents this behavior作为一种安全措施,他们有一个relevant ticket 记录why they do this

这也是为什么某些网站(例如 github)会警告用户,如果在一个选项卡中完成登录/注销,他们需要在用户浏览器会话的所有其他选项卡上重新加载页面。没有安全措施可以避免这种情况。

【讨论】:

  • 如果您检测到身份验证 cookie 已更改,我认为您可以自动刷新页面(或仅刷新某些部分)。我认为这就是谷歌处理这种情况的方式。
  • 感谢您的文档参考。不过,我不确定我是否理解您的前两句话。在第 1 步生成一个 csrf 令牌(我们称之为 csrf-1)。当(同一)用户打开辅助选项卡时,发送 csrf-1 - 并原封不动地返回。当用户登录时(在辅助选项卡中),csrf-1 令牌从浏览器发送到服务器,并从服务器返回一个新的 csrf 令牌 (csrf-2) 并在浏览器中设置。 csrf-2 与原始选项卡上表单中的 input=hidden csrf-1 标记不匹配。
  • @thebjorn csrf-1 是作为原始匿名用户生成的,因此理论上可以由另一个敌对匿名用户生成相同的令牌。如果恶意用户可以欺骗原始匿名用户访问他们的页面,并说服他们登录 django 站点,如果原始 csrf 令牌仍然有效,则攻击者可以触发 post 操作以提交他们的数据版本代表原始用户,从而触发 csrf 攻击(尽管这是人为的,这个攻击向量是真实的)。
  • @metatoaster 我不确定恶意匿名用户如何生成相同的令牌。听起来您是在说 csrf-1 在所有匿名用户之间共享,但事实并非如此。在 GET 请求(其中响应包含表单)中,可能会发生以下两种情况之一:如果浏览器以前从未访问过该站点,则不会将 Cookie: 标头从浏览器发送到服务器,并且服务器将生成新鲜/独特的 csrf 令牌并通过 Set-Cookie: 标头返回。如果它是一个已知站点,服务器将简单地回显浏览器发送的 csrf 令牌。
  • 正如我所说,这在理论上是可能的,如果匿名 CSRF 令牌生成存在漏洞,这可能会受到损害,这就是为什么从不总是好的原因> 在上下文更改时混合/回收令牌以完全且肯定地消除此类攻击。
【解决方案2】:

对于这个确切的问题,如果 Django 的 CSRF_COOKIE_HTTPONLY 的默认值为 False,这个 onfocus 处理程序似乎可以工作:

$(document).ready(function () {
    $(window).on('focus', function () {

         var cookie_csrf = dk.web.cookie.get('csrftoken');  // or Cookie.get(..) or something similar
         var dom_csrf = $('[name=csrfmiddlewaretoken]:first');

         if (cookie_csrf !== dom_csrf) {
             // other tab has caused the csrf cookie to change
             $('[name=csrfmiddlewaretoken]').each(function () {
                 $(this).val(cookie_csrf);
             });
         }
    });
});

这似乎有点骇人听闻,所以刷新页面也许“更好”:

if (cookie_csrf !== dom_csrf) {
    window.location.reload(true);  // reload the current page, without using the cache
}

刷新页面将获得因登录而导致的页面更改,但会删除用户输入的任何输入。

假设您没有 XSS 漏洞(通常在涉及 csrf 时假设),从 .js 访问 csrf 令牌是安全的。

这种技术依赖于 cookie 和 dom 中的 csrf 令牌的值相同的事实,这在 Django 中是设计的。

【讨论】:

    猜你喜欢
    • 2012-01-30
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    • 2016-05-23
    • 2015-05-21
    相关资源
    最近更新 更多