暴露会话的CSRF保护令牌是否安全?

Joh*_*kin 17 security django ajax csrf

Django附带了CSRF保护中间件,它可以生成一个独特的每会话令牌,用于表单.它会扫描所有传入的POST请求以获取正确的令牌,并在令牌丢失或无效时拒绝该请求.

我想将AJAX用于一些POST请求,但是所述请求没有CSRF令牌可供选择.页面没有<form>可以挂钩的元素,我宁愿不把标记作为隐藏值插入标记.我认为这样做的一个好方法是公开一个/get-csrf-token/想要返回用户令牌的vew ,依靠浏览器的跨站点脚本规则来防止恶意站点请求它.

这是一个好主意吗?是否有更好的方法来防止CSRF攻击,同时仍允许AJAX请求?

Car*_*yer 16

更新:以下是真的,如果所有浏览器和插件都正确实现,应该是真的.不幸的是,我们现在知道它们不是,并且浏览器插件和重定向的某些组合可以允许攻击者在跨域请求上提供任意标头.不幸的是,这意味着即使带有"X-Requested-With:XMLHttpRequest"标头的AJAX请求现在也必须受CSRF保护.因此,Django 不再免除来自CSRF保护的Ajax请求.

原始答案

值得一提的是,保护来自CSRF的AJAX请求是不必要的,因为浏览器不允许跨站点AJAX请求.实际上,Django CSRF中间件现在可以自动免除来自CSRF令牌扫描的AJAX请求.

这仅在您实际检查X-Requested-With标头服务器端的"XMLHttpRequest"值(Django所做的)时才有效,并且只从CSRF扫描中免除真正的AJAX请求.

  • @Nathan你不能"通过许多不同的方法从其他任何地方创建相同的帖子请求",因为浏览器会拒绝执行该帖子请求(除非你可以让我的域服务你的JS,在这种情况下我显然有另一个洞).您必须绕过相同的域限制,或欺骗用户的浏览器执行非AJAX请求并欺骗X-Requested-With标头.无论哪种方式,如果你能够做到这是一个浏览器错误.工作演示欢迎. (2认同)
  • @Nathan再次,不.你可以让用户的浏览器POST到我的域,当然,如果它是一个普通的表单提交,它将不是一个AJAX请求(根据我检查服务器端的X-Requested-With标头).并且您不能强制用户的浏览器添加该标头而不会违反相同域AJAX限制.如果可以的话,这是一个浏览器错误.再说一次:如果您认为这是可能的,请构建一个演示,以显示它在运行中. (2认同)
  • @Carl Meyer - 在再次审核您的评论并仔细查看您的答案中包含的链接后,我现在同意您的意见.:-)你必须编辑你的答案才能让我改变我的投票.感谢在这次讨论中与我合作,我学到了一些东西. (2认同)

Mat*_*ell 13

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

换句话说:通过Django的模板 - 而不是通过URL调度程序.这种方式更加安全.