我正计划构建一个具有分离的前端和后端的应用程序(仅使用ajax请求)。我不允许跨站点的ajax请求。我是否可以通过添加一个类似于/ csrf的API来生成带有ajax调用的csrf token ,该API返回以下内容:{csrf:'token'}以下网站说我绝对不能这样做:https://github.com/pillarjs/understanding-csrf
Make sure CSRF tokens can not be accessed with AJAX! Don't create a /csrf route just to grab a token, and especially don't support CORS on that route!
是否有特定原因?我了解CORS背后的原因-已被禁用,但是通过Ajax提供csrf token 是否存在任何固有的安全风险?
最佳答案
这不是安全风险,原因如下:
为什么甚至要通过AJAX公开CSRF token ?
从可用性的 Angular 来看,如果您不提供通过AJAX获取CSRF token 的方法,并且没有使用Double Submit Cookie方法(完全避免了此问题)之类的方法,则您的网站使用起来可能会很麻烦因为打开多个标签的任何人都会遇到有关CSRF token 不匹配的错误。
在使用CSRF token 的网站上,如果您在提交POST请求之前可以通过表单获取最新的CSRF token ,那么对用户来说会是更好的体验。
现代的单页应用程序网站(例如,使用React或Angular构建的通用站点)也需要一种轻松获取CSRF token 的方法,这得益于CSRF token 给出的投影,就像传统的仅基于服务器渲染的站点一样。
CSRF token 与 session 相关联
CSRF token 与 session 绑定(bind)-即使您未显式登录,CSRF token 仍需要与客户端和服务器之间跟踪的 session 绑定(bind)。
如果您的 session token 具有HTTP Only cookie(这是最佳做法,可防止XSS攻击窃取并有助于保护您免受CSRF攻击),则没人可以通过远程域从请求中读取CSRF token (即使浏览器不执行CORS!)。
跨域资源共享
在这样的讨论中,CORS引起了很多反响,但实际上这是个红色鲱鱼。
安全性实际上归结为对您的sesison cookie使用HTTP Only cookie,并且对具有 session token 的cookie具有相同的域策略–自从黎明之初以来,所有浏览器都支持(带有MSIE的极端情况警告,将cookie暴露给其他浏览器没有的子域)。
如果远程站点上的某些JavaScript无法读取您的 session token (如果位于您域中的HTTP Only Cookie中,则无法读取 session token ),那么它就无法读取CSRF token !
如果仅使用HTTP cookie和CSRF token ,我是否可以抵御CSRF和XSS攻击?
您应该免受CSRF攻击的威胁,并且不受某些类型的XSS攻击的保护,但是XSS仍然存在风险。
如果有人找到一种使用XSS的方法在您的网站上执行任意JavaScript并创建来自您的域的请求,那么此时CSRF,仅HTTP cookie或 session 指纹都无法为您提供保护-任何执行的操作都看起来像它是由用户触发的。
尽管对于不可逆转的破坏性操作或潜在的昂贵操作而言,按要求提供的验证码将提供一些额外的保护,从外部确认操作(例如通过电子邮件,SMS等)是一个好主意。
但是安全要比后悔好吗?
如果您仍然担心CSRF的AJAX端点可能以某种您不了解的方式成为 vector ,请考虑能够执行来自您域的请求并解析响应的远程脚本可能同样会触发请求到具有表单的页面,并从<input>
上的<form>
值获取CSRF token 。
同样,如果某人能够在您的网站上执行任意JavaScript并以他们所针对的当前用户身份发出和读取请求,那么从您的DOM中读取CSRF token 并将其从已经存在的表单中提取出来会容易得多。页面比使用AJAX更为困惑。
摘要
使用仅HTTP cookie和CSRF token 可帮助抵御CSRF和XSS攻击。
另外,您也不能在给定的 session 中轮换用户CSRF token (某些中间件实际上是在这样做,以避免完全解决问题),但是值得注意的是,对于大多数CSRF token 库而言,这并不是典型的默认行为。
开放Web应用程序安全性项目中的OWASP CSRF Cheat Sheet是一个很好的资源,它会更详细。
关于javascript - 通过AJAX获取CSRF token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33574343/