我正在为一组网站设计API。这些站点非常相似(有点像StackOverflow,SuperUser和ServerFault),并且他们有一个共享的后端是合理的。因此,我们决定尝试使用一个很好的REST API作为后端,以及一些使用API的非常相似但不同的前端。前端应该最好全部是静态的,但如果事实证明这是不可能的,那么这并不是一个硬性要求。如何保护浏览器从CSRF攻击中使用的RESTful API?
我正在设计API,我担心安全问题,特别是CSRF。从我对CSRF攻击的基本理解来看,它们包含两个重要组件:
能够命名资源和请求正文。
欺骗用户/浏览器使用环境认证(如会话)向该资源寻求认证的请求。
很多修复CSRF攻击的经典方法都基于会话。由于我的REST API并没有真正执行会话,因此它们都会阻止很多向量,并且几乎可以解决所有这些问题。例如,双提交没有意义,因为没有什么可以提交。
我最初的方法是攻击CSRF攻击的第2部分。如果我对所有请求进行了身份验证(比如使用HTTP Basic Auth),并且浏览器不保存这些证书(例如,某些JS发出请求),那么只有拥有凭证的JS才能发出请求,并且我们完成了。明显的缺点是应用程序需要知道用户的凭据。另一个稍微不太明显的缺点是,如果我想在API端安全地存储凭据,那么验证密码应该花费固定的,不重要的时间量。如果安全地验证密码需要100ms,那么其他每个请求至少需要100ms + eps,并且这会让一些聪明的客户端欺骗手段使其不那么慢。我可能能够缓存这些信息(因为证书总是相同的),如果我非常小心,我可能会设法做到这一点,而不会引入定时漏洞,但这听起来像是一个黄蜂巢。
OAuth 2.0似乎有点过分了,但我想这可能是最好的解决方案,以免我最终实施得不好。我想我现在可以做HTTP基本身份验证的事情,当我们有第三方应用程序开发人员时,转到OAuth。
OAuth有一点阻抗不匹配。基本上,OAuth真的想帮助应用程序访问另一个应用程序的内容。我希望用户在这样一个帐户存在之前注册其中一个前端。
我也考虑过攻击点1,通过使URL随机化 - 即将标记添加到查询字符串。这肯定会起作用,它与表单中传统的随机化令牌非常接近,并且给予HATEOAS它应该甚至是相当RESTful,尽管这提出了两个问题:1)您从哪里开始?在使用HTTP Basic Auth进行登录时,是否有必要的API起始点? 2)如果他们不能事先预测URL,HATEOAS会被定罪吗?
我看过How to prevent CSRF in a RESTful application?,但我不同意这样一个前提,即随机化的URI必然是不可靠的。另外,这个问题并没有真正的答案,也没有提到OAuth。此外,会话双提交解决方案是无效的,正如我上面提到的(静态前端的不同域比API端点)。
我意识到我从根本上试图在这里做的是试图允许来自一个域的跨站点请求,并禁止从另一个域请求,这并不容易。当然必须有一些合理的解决方案?
的问题,就像你说的,是要既防止和允许跨站点请求。问薛定谔。 –
这并不意味着没有办法解决问题。我甚至提供了一个,尽管有点慢。 – lvh