暴露会话的 CSRF 保护令牌安全吗?
Django 附带 CSRF 保护中间件,它会生成一个独特的用于表单中的每个会话令牌。 它会扫描所有传入的 POST 请求以获取正确的令牌,如果令牌丢失或无效,则拒绝该请求。
我想对某些 POST 请求使用 AJAX,但所述请求没有可用的 CSRF 令牌。 这些页面没有可挂钩的
这是一个好主意吗? 是否有更好的方法来防止 CSRF 攻击,同时仍然允许 AJAX 请求?
Django comes with CSRF protection middleware, which generates a unique per-session token for use in forms. It scans all incoming POST
requests for the correct token, and rejects the request if the token is missing or invalid.
I'd like to use AJAX for some POST requests, but said requests don't have the CSRF token availabnle. The pages have no <form>
elements to hook into and I'd rather not muddy up the markup inserting the token as a hidden value. I figure a good way to do this is to expose a vew like /get-csrf-token/
to return the user's token, relying on browser's cross-site scripting rules to prevent hostile sites from requesting it.
Is this a good idea? Are there better ways to protect against CSRF attacks while still allowing AJAX requests?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
更新:以下内容是正确的,并且如果所有浏览器和插件都正确实现,则应该是正确的。 不幸的是,我们现在知道事实并非如此,并且浏览器插件和重定向的某些组合可以允许攻击者在跨域请求上提供任意标头。 不幸的是,这意味着即使带有“X-Requested-With: XMLHttpRequest”标头的 AJAX 请求现在也必须受到 CSRF 保护。 因此,Django 不再免除 Ajax 请求的 CSRF 保护。
原始答案
值得一提的是,没有必要保护 AJAX 请求免受 CSRF 的影响,因为浏览器不允许跨站点 AJAX 请求。 事实上,Django CSRF 中间件现在自动免除 AJAX 请求的 CSRF 令牌扫描。
仅当您实际在服务器端检查 X-Requested-With 标头的“XMLHttpRequest”值(Django 所做的),并且仅从 CSRF 扫描中免除真正的 AJAX 请求时,这才有效。
UPDATE: The below was true, and should be true if all browsers and plugins were properly implemented. Unfortunately, we now know that they aren't, and that certain combinations of browser plugins and redirects can allow an attacker to provide arbitrary headers on a cross-domain request. Unfortunately, this means that even AJAX requests with the "X-Requested-With: XMLHttpRequest" header must now be CSRF-protected. As a result, Django no longer exempts Ajax requests from CSRF protection.
Original Answer
It's worth mentioning that protecting AJAX requests from CSRF is unnecessary, since browsers do not allow cross-site AJAX requests. In fact, the Django CSRF middleware now automatically exempts AJAX requests from CSRF token scanning.
This is only valid if you are actually checking the X-Requested-With header server-side for the "XMLHttpRequest" value (which Django does), and only exempting real AJAX requests from CSRF scanning.
如果您知道 AJAX 请求需要 CSRF 令牌,则可以随时将其嵌入 HTML 中的某个位置; 那么你可以通过Javascript通过遍历DOM来找到它。 这样,您仍然可以访问令牌,但不会通过 API 公开它。
换句话说:通过 Django 的模板来完成——而不是通过 URL 调度程序。 这样就安全多了。
If you know you're going to need the CSRF token for AJAX requests, you can always embed it in the HTML somewhere; then you can find it through Javascript by traversing the DOM. This way, you'll still have access to the token, but you're not exposing it via an API.
To put it another way: do it through Django's templates -- not through the URL dispatcher. It's much more secure this way.
取消那个,我错了。 (请参阅评论。) 您可以通过确保 JSON 遵循规范来防止漏洞利用:始终确保返回对象文字作为顶级对象。 (我不能保证不会有进一步的利用。想象一下浏览器在其 window.onerror 事件中提供对失败代码的访问!)
您不能依赖跨站点脚本规则来保持 AJAX 响应的私密性。 例如,如果您以 JSON 形式返回 CSRF 令牌,恶意网站可能会 重新定义 String 或 Array 构造函数 并请求资源。
bigmattyh 是正确的:您需要将令牌嵌入到标记中的某个位置。 或者,您可以拒绝任何确实具有不匹配引荐来源网址的 POST。 这样,只有拥有过度软件防火墙的人才会容易受到 CSRF 的攻击。
Cancel that, I was wrong. (See comments.) You can prevent the exploit by ensuring your JSON follows the spec: Always make sure you return an object literal as the top-level object. (I can't guarantee there won't be further exploits. Imagine a browser providing access to the failed code in its window.onerror events!)
You can't rely on cross-site-scripting rules to keep AJAX responses private. For example, if you return the CSRF token as JSON, a malicious site could redefine the String or Array constructor and request the resource.
bigmattyh is correct: You need to embed the token somewhere in the markup. Alternatively, you could reject any POSTs that do have a referer that doesn't match. That way, only people with overzealous software firewalls will be vulnerable to CSRF.
我猜它很容易受到攻击,如果你有一个 django 后台和一个单独的前端,那么当然会出现问题,所以最好的解决方案是如果有办法将某些域或 url 列入白名单,不受 csrf 豁免......这样..只有单独的白名单前端可以向相应的后端发出请求..
尽管我还没有遇到任何类似的解决方案
It is i guess vulnerable, if you have a django back and a separate frontend then of course there is going to be problem, so the best soultion would be if there was a way to whitelist some domains or urls from the csrf exempts ... in that way .. only the separate whitelisted frontend can make requests to the respective backend..
though i havent come across any solution like that yet