django:csrftoken COOKIE与csrfmiddlewaretoken HTML表单值

jd.*_*jd. 18 django

试图了解安全性.想知道为什么在django提交表单(POST)时,有两个单独的"元素"包含相同的csrf标记值:

- the csrftoken cookie:
     COOKIES:{'csrftoken': '1effe96056e91a8f58461ad56c0d4ddc', ...

- the Form's hidden csrfmiddlewaretoken:
     POST:<QueryDict: {u'csrfmiddlewaretoken': 
                       [u'1effe96056e91a8f58461ad56c0d4ddc'], ...
Run Code Online (Sandbox Code Playgroud)

如果django在将表单发送到浏览器(GET)时将隐藏的csrf字段/值插入到表单中,并且在接收POST时期望返回相同的值,那么为什么还需要设置cookie呢?

一个更一般的问题,如果其中任何一个缺失(表单,cookie),您是否可以提供一个方案来解释如何利用它(安全攻击)?

顺便说一句,我运行了几个简单的测试,以确保django分别检查每个测试的有效性,实际上它是:

  • 如果我在执行POST之前更改了表单的csrf值,我会收到此调试错误:

    CSRF令牌丢失或不正确

  • 如果我在执行POST之前删除了csrf cookie,我会收到不同的错误:

    未设置CSRF cookie.

我只熟悉基本的csrf概念,并想了解django如何帮助抵御这些类型的攻击.

谢谢,

JD


更新:

虽然这两个答案(S.Lott和M. DeSimone)都提供了信息并且有意义,但我认为可能有更详细的解释要求在表单和cookie中都存在安全值.在stackoverflow.com外搜索时,我发现了一篇来自... Jeff Atwood的博文.

我已经包含了第三个答案(很抱歉回答我自己的问题,但我认为这是相关的补充信息),它引用了Jeff的博客文章并包含了引文.

jd.*_*jd. 19

来自Jeff Atwood的博客文章:

防止CSRF和XSRF攻击(2008年10月14日)

原帖

Felten和Zeller论文(pdf)推荐使用"双提交cookie"方法来防止XSRF:

当用户访问站点时,站点应生成(加密强)伪随机值并将其设置为用户计算机上的cookie.该网站应要求每个表单提交包括此伪随机值作为表单值以及cookie值.当POST请求发送到站点时,只有表单值和cookie值相同时才应认为该请求有效.当攻击者代表用户提交表单时,他只能修改表单的值.根据同源策略,攻击者无法读取从服务器发送的任何数据或修改cookie值.这意味着虽然攻击者可以使用表单发送他想要的任何值,但他将无法修改或读取存储在cookie中的值.由于cookie值和表单值必须相同,因此攻击者将无法成功提交表单,除非他能够猜测伪随机值.

这种方法的优点是它不需要服务器状态; 您只需设置一次cookie值,然后每次HTTP POST检查以确保其中一个提交的值包含完全相同的cookie值.两者之间的任何差异意味着可能的XSRF攻击.


Mik*_*one 7

该cookie用于支持AJAX.引用Django文档:

虽然上述方法可用于AJAX POST请求,但它有一些不便之处:您必须记住在每次POST请求时将CSRF令牌作为POST数据传递.因此,有一种替代方法:在每个XMLHttpRequest上,将自定义X-CSRFToken标头设置为CSRF标记的值.这通常更容易,因为许多javascript框架提供了允许在每个请求上设置标头的钩子.在jQuery中,您可以使用ajaxSend事件,如下所示:

$('html').ajaxSend(function(event, xhr, settings) {
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
        // Only send the token to relative URLs i.e. locally.
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
});
Run Code Online (Sandbox Code Playgroud)

将此添加到您的站点上包含的javascript文件将确保通过jQuery创建的AJAX POST请求不会被CSRF保护捕获.


S.L*_*ott 6

他们发现了两个不同的问题

Cookie用于验证进行连接的客户端计算机.

隐藏的表单字段用于验证表单的来源.

示例场景:客户端计算机上的用户A可以为表单添加书签.用户B登录,从今天开始获取有效的cookie.当浏览器具有来自用户B的会话的剩余cookie时,用户A可以从昨天提交无效表单字段.


通常会破坏哪些客户端/浏览器资源,

没有.

以及这些csrf字段如何帮助保护我们免受伪造请求的影响?

CSRF令牌建立身份.

一个(且仅一个)浏览器具有CSRF cookie令牌.但该浏览器可能有多个网站打开或书签形式的副本.

该浏览器上的一个(且仅一个)页面表单具有CSRF表单令牌.

浏览器和表单cookie必须匹配以确保一个浏览器/一个表单.