RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1099026
Accepted
JBlack
JBlack
Asked:2020-03-24 17:34:01 +0000 UTC2020-03-24 17:34:01 +0000 UTC 2020-03-24 17:34:01 +0000 UTC

姜戈。模板和 cookie 中的 CSRF 令牌不匹配

  • 772

标准情况是在 Django 中处理 HTML 表单。在表单中的模板中{% csrf_token %},它应该是注册的。任务是使用纯 JS 方法在 ajax 函数中实现一个简单的功能,即 通过对象XMLHttpRequest。要使此功能与 Django 一起使用,您需要XMLHttpRequest通过csrf_token. 令牌的值由 JS 脚本通过以下命令从站点的 cookie 中获取:

var csrfCookie = document.cookie.match(/csrftoken=([\w-]+)/); 

并插入到 HTTP 请求标头中:

Request = new XMLHttpRequest();
Request.setRequestHeader("X-CSRFToken", csrfCookie);

令牌的值是正确的,但总是相同的,而模板中令牌的值总是不同的,应该是这样。因此,向服务器发送请求时会出现令牌不匹配错误。当然,令牌不匹配的问题现在已经解决了,但是通过hidden input在 Django 用于此目的的 HTML 表单中获取当前令牌的值的解决方法:

<input type="hidden" name="csrfmiddlewaretoken" value="CSRF-токен">

当前隐藏表单域token的值:

var csrfCookie = document.getElementsByName("csrfmiddlewaretoken")[0].value;

然而,原则上这个问题仍然悬而未决,因为不清楚为什么相同的 CSRF 令牌值存在于 cookie 中。顺便说一句,django 文档提供了一个 JS 脚本函数来获取这个值,并再次通过 cookie 处理。

对此有两个问题: 1.为什么在这种情况下,cookie 中的 CSRF 令牌的值不会随着 HTML 表单页面的每次更新而改变,而表单内部的令牌本身总是不同的。 2.实际上,当令牌的值可以从 cookie 或表单本身的隐藏输入中获取时,安全性在哪里?

ajax
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Vadim.Sharoikin
    2020-03-24T20:22:21Z2020-03-24T20:22:21Z

    CSRF 攻击示例(来自 Wikipedia) 攻击是通过在网页上放置链接或脚本来执行的,该网页试图访问已知(或可能)已通过身份验证的受攻击用户的站点。例如,用户 Alice 可能正在浏览另一个用户 Bob 发布消息的论坛。让 Bob 创建一个标签,其中指定 URL 作为图片的来源,当点击它时,在 Alice 的银行网站上执行一个动作,例如: Bob: Hello, Alice!看看多可爱的猫:<img src="http://bank.example.com/withdraw?account=Alice&amount=1000000&for=Bob"> 如果 Alice 的银行将 Alice 的认证信息存储在 cookie 中,并且如果 cookie 还没有过期,当 Alice 尝试下载图片时,Alice 的浏览器会在请求中发送一个 cookie 向 Bob 的账户转账,这将确认 Alice 的认证。因此,交易将成功完成,尽管它的确认将在 Alice 不知情的情况下发生。换句话说,cookie 不能保证是 Alice 创建了表单。他们只验证身份,而不是数据。

    保护站点的典型方法是使用“密钥”,这是一个随机生成并存储在访问者会话中的特殊值。只有服务器知道,我们甚至不会向访问者展示。

    1 cookie 中 CSRF 令牌的值没有变化,因为默认值为CSRF_COOKIE_AGE31449600(1 年,以秒为单位)。表单内部的令牌本身是不同的,因为它是使用django.middleware.csrf.CsrfViewMiddleware服务器上的密钥生成的(基于cookies)。不知道密钥,就不可能生成服务器会认为正确的令牌。

    2只有当有人可以访问用户的计算机时,才能获取令牌的价值。但是他根本不需要CSRF,tk。有更简单的方法可以自己发送请求。

    • 1
  2. JBlack
    2020-03-24T20:57:47Z2020-03-24T20:57:47Z

    来自 Django 文档(翻译)

    这个怎么运作:

    CSRF 保护基于以下几点:

    基于其他站点无法访问的随机秘密值的 CSRF cookie。

    此 cookie 已设置CsrfViewMiddleware。django.middleware.csrf.get_token()如果尚未在请求中设置它,则它与它调用的每个响应(内部用于获取 CSRF 令牌的函数)一起发送。

    为了防止 BREACH 攻击,令牌不仅仅是一个秘密;将随机盐添加到密钥中并用于对其进行加密。

    出于安全原因,每次用户登录时,secret 的值都会发生变化。

    csrfmiddlewaretoken所有传出的 POST 表单中都存在一个名为“”的隐藏表单字段。同样,该字段的值是添加了盐并用于对其进行加密的密钥的值。每次调用都会重新生成盐get_token(),因此表单字段的值会在每次此类响应时发生变化。

    这部分由模板标签完成。

    对于所有不使用 HTTP GET、HEAD、OPTIONS 或 TRACE 的传入请求,必须存在 CSRF cookie 并且“ csrfmiddlewaretoken”字段必须存在且有效。如果不是,用户将收到 403 错误。

    在检查 " csrfmiddlewaretoken" 字段的值时,仅将秘密而不是完整的令牌与 cookie 值中的秘密进行比较。这允许使用不断变化的令牌。尽管每个请求都可以使用自己的令牌,但秘密仍然由所有人共享。

    该检查正在进行中CsrfViewMiddleware。

    此外,对于 HTTPS 请求,它CsrfViewMiddleware执行严格的链接检查。这意味着即使子域可以在您的域上设置或修改 cookie,它也不能强制用户发布到您的应用程序,因为该请求不会来自您自己的确切域。

    这也适用于在 HTTPS 下使用与会话无关的密钥时可能发生的中间人攻击,因为即使客户端通过 HTTPS 与站点进行通信,HTTP Set-Cookie 标头也会被客户端接受(不幸的是) . 不对 HTTP 请求执行Referer 验证,因为在 HTTP 上具有Referer 标头不够可靠。)

    如果设置了 CSRF_COOKIE_DOMAIN 参数,则将引用者与其进行比较。此设置支持子域。例如,CSRF_COOKIE_DOMAIN = '.example.com' 将允许来自 www.example.com 和 api.example.com 的 POST 请求。如果未设置该设置,则引用者必须与 HTTP 主机标头匹配。

    可以使用CSRF_TRUSTED_ORIGINS.

    这确保只有从受信任域接收的表单才能用于返回 POST 数据。

    它故意忽略 GET 请求(以及在 RFC 7231#section-4.2.1 中定义为“安全”的其他请求)。这些请求不应该有潜在的危险副作用,因此使用 GET 请求攻击 CSRF 应该是无害的。RFC 7231# section-4.2.1 将 POST、PUT 和 DELETE 定义为“不安全”,所有其他方法也被认为是不安全的,以提供最大程度的保护。

    CSRF 保护无法防止中间人攻击,因此请使用带有 HTTP 严格传输安全性的 HTTPS。这还假设检查 HOST 标头并且您的站点上没有任何跨站点脚本漏洞(因为 XSS 漏洞已经允许攻击者执行 CSRF 漏洞允许的所有事情,甚至更糟)。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5