Ajax 正在公开一个会话';s CSRF保护令牌安全吗?

Ajax 正在公开一个会话';s CSRF保护令牌安全吗?,ajax,django,security,csrf,Ajax,Django,Security,Csrf,Django附带了一个单独的会话令牌,用于表单中。它扫描所有传入的POST请求,以查找正确的令牌,如果令牌丢失或无效,则拒绝请求 我想对一些POST请求使用AJAX,但所说的请求没有可用的CSRF令牌。这些页面没有要挂接的元素,我不希望将标记作为隐藏值插入时弄乱标记。我认为这样做的一个好方法是公开一个vew,如/get csrf token/,以返回用户的令牌,依靠浏览器的跨站点脚本规则来防止恶意站点请求它 这是个好主意吗?在仍然允许AJAX请求的情况下,是否有更好的方法来防止CSRF攻击?如果

Django附带了一个单独的会话令牌,用于表单中。它扫描所有传入的
POST
请求,以查找正确的令牌,如果令牌丢失或无效,则拒绝请求

我想对一些POST请求使用AJAX,但所说的请求没有可用的CSRF令牌。这些页面没有要挂接的
元素,我不希望将标记作为隐藏值插入时弄乱标记。我认为这样做的一个好方法是公开一个vew,如
/get csrf token/
,以返回用户的令牌,依靠浏览器的跨站点脚本规则来防止恶意站点请求它


这是个好主意吗?在仍然允许AJAX请求的情况下,是否有更好的方法来防止CSRF攻击?

如果您知道AJAX请求需要CSRF令牌,您可以随时将其嵌入HTML中的某个位置;然后您可以通过Javascript遍历DOM找到它。这样,您仍然可以访问令牌,但不会通过API公开它


换言之:通过Django的模板完成,而不是通过URL调度程序。这样更安全。

取消那个,我错了。(请参阅注释。)您可以通过确保JSON符合规范来防止利用漏洞:始终确保返回一个对象文字作为顶级对象。(我不能保证不会有进一步的漏洞利用。想象一下,一个浏览器在它的window.onerror事件中提供对失败代码的访问!)

您不能依靠跨站点脚本规则来保持AJAX响应的私密性。例如,如果您将CSRF令牌作为JSON返回,则恶意站点可能会访问并请求资源


bigmattyh是正确的:您需要将令牌嵌入标记中的某个位置。或者,您可以拒绝任何确实有不匹配的推荐人的帖子。这样的话,只有那些拥有过度热情的软件防火墙的人才会容易受到CSRF的攻击。

更新:下面的说法是正确的,如果所有浏览器和插件都得到了正确的实现,那么应该是正确的。不幸的是,我们现在知道它们不是,并且浏览器插件和重定向的某些组合允许攻击者在跨域请求中提供任意头。不幸的是,这意味着即使是带有“X-request-with:XMLHttpRequest”头的AJAX请求现在也必须受到CSRF保护。因此,Django

原始答案

值得一提的是,保护来自CSRF的AJAX请求是不必要的,因为浏览器不允许跨站点AJAX请求。事实上,Django CSRF中间件现在已经过时了


只有在您实际检查X-request-With-header服务器端的“XMLHttpRequest”值(Django会这样做),并且仅从CSRF扫描中免除真正的AJAX请求时,这才有效。

Ugh,再次检查该链接。至少作者在结尾加了一句话,说他错了。JSON实际上不易被重新定义构造函数所攻击,因为当您试图解析未经修饰的JSON时,Javascript解析器将引发异常。这不是真的。ajax请求显然是在与服务器(您的)通信。作为攻击者,我仍然可以通过许多不同的方法从其他任何地方创建相同的post请求,如果用户登录,没有CSRF保护,我将成功。@Nathan您不能“通过许多不同的方法从其他任何地方创建相同的post请求”,因为浏览器将拒绝执行该post请求(除非你能让我的域名为你的JS服务,在这种情况下,我显然还有另一个漏洞)。您必须绕过相同的域限制,或者欺骗用户的浏览器执行非AJAX请求并使用标头欺骗X-Requested-With。无论哪种方式,如果您能够这样做,这都是一个浏览器错误。欢迎使用演示。@Carl Meyer:我仍然不同意。我可以(例如)将用户吸引到我控制的网站,该网站以与AJAX请求相同的方式向服务器发送帖子-无需向您的网站注入javascript。普通http帖子没有相同的域限制-我可以以任何形式向任何域发布。cookie随请求一起发送,而不是随页面一起发送。这仍然属于跨站点请求伪造的类别。@Nathan,再次,不。您可以让用户的浏览器发布到我的域,当然,但如果是普通表单提交,则不会是AJAX请求(根据我正在检查服务器端的X-Requested-With头)。并且,如果不违反相同的域AJAX限制,则无法强制用户的浏览器添加该标题。如果可以,则这是一个浏览器错误。再次声明:如果您认为这是可能的,请构造一个演示,在运行中显示该标题。@Carl Meyer-再次查看您的评论并更仔细地查看您的文档中包含的链接后回答,我现在同意你的意见。:-)你必须先编辑你的答案,然后让我更改我的投票。感谢您在这次讨论中对我的支持,我学到了一些东西。CSRF令牌应该随着每次操作而变化。您是否建议每个操作都更新令牌?这是否意味着用户的操作必须是同步的(在第一个操作返回并提供新的csrf令牌之前,第二个操作无法启动)。这不是最好的答案。正如Carl Meyer在他的回答中所说:没有必要在Django中使用令牌来保护来自CSRF的AJAX请求,因为Django已经以不同的方式保护AJAX请求。这也消除了神秘主义者的担忧。也许这会有所帮助,即使我没有整理关于ajax和CSRF的故事,@amirouche的这个文档链接很有用。我们现在可以
xhr.setRequestHeader(“X-CSRFToken”,CSRFToken)
从cookie
$.cookie('CSRFToken')
获取令牌。这甚至更安全,因为令牌在任何地方都不会出现。