尝试了解安全性。好奇为什么在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的博客文章。
我已经包含了第三个答案(很抱歉回答我自己的问题但是 我认为这是相关的补充信息)是指博客 杰夫的帖子,包含一个引文。
答案 0 :(得分:18)
来自Jeff Atwood的博客文章:
防止CSRF和XSRF攻击 (2008年10月14日)
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保护捕获。