django:csrftoken COOKIE与csrfmiddlewaretoken HTML表单值

时间:2011-04-07 22:22:41

标签: django

尝试了解安全性。好奇为什么在django时 提交表格(POST),有2个单独的“元素” 包含相同的csrf标记值:

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

- the Form's hidden csrfmiddlewaretoken:
     POST:<QueryDict: {u'csrfmiddlewaretoken': 
                       [u'1effe96056e91a8f58461ad56c0d4ddc'], ...

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

一个更一般的问题,如果其中任何一个缺失(形式,cookie), 你能提供一个场景来解释如何利用它 (安全攻击)?

顺便说一下,我运行了几个简单的测试来确保这一点 django分别检查每个人的有效性 确实是:

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

    CSRF令牌缺失或不正确

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

    CSRF cookie未设置。

我只是熟悉基本的csrf概念并且想要 了解django如何帮助抵御这些类型的攻击。<​​/ p>

谢谢,

JD


更新:

尽管两个答案(S.Lott和M. DeSimone)都提供了丰富的信息 有道理,我认为可以有更详细的解释 要求在形式和形式中都存在安全值 在cookie中。在stackoverflow.com外搜索时,我遇到了 来自... Jeff Atwood的博客文章。

我已经包含了第三个答案(很抱歉回答我自己的问题但是 我认为这是相关的补充信息)是指博客 杰夫的帖子,包含一个引文。

3 个答案:

答案 0 :(得分:18)

来自Jeff Atwood的博客文章:

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

The original post

Felten和Zeller论文(pdf)建议“双重提交     cookie“防止XSRF的方法:

  

当用户访问网站时,该网站应生成一个         (加密强)伪随机值并将其设置为         用户机器上的cookie。该网站应该要求每个表格         提交以将此伪随机值包括为表单值和         也作为cookie值。当POST请求发送到站点时,         如果表单值和,请求只应被视为有效         cookie值是相同的。当攻击者提交表单时         代表用户,他只能修改表单的值。一个         攻击者无法读取从服务器发送的任何数据或修改cookie         根据同源政策的价值观。这意味着,虽然         攻击者可以通过表单发送他想要的任何值,他会         无法修改或读取存储在cookie中的值。自从         cookie值和表单值必须相同,攻击者会         除非能够猜测,否则无法成功提交表格         伪随机值。

     

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

答案 1 :(得分:6)

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

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

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

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


  

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

无。

  

这些csrf字段如何帮助保护我们免受伪造请求的侵害?

CSRF令牌建立身份。

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

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

浏览器和表单Cookie必须匹配才能确保一个浏览器/一个表单。

答案 2 :(得分:6)

该cookie用于支持AJAX。引用Django docs

  

虽然上述方法可用于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'));
    }
});
  

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