如何保护浏览器使用的RESTful API免受CSRF攻击

How do you secure a RESTful API being consumed by a browser from CSRF attacks?

本文关键字:RESTful API 免受 攻击 CSRF 何保护 保护 浏览器      更新时间:2023-09-26

我正在为一组站点设计API。这些站点非常相似(有点像StackOverflow、SuperUser和ServerFault),因此它们有一个共享的后端是有意义的。因此,我们决定尝试使用一个不错的REST API作为后端,并使用一堆非常相似但又不同的前端。前端最好都是静态的,但如果结果是不可能的,这不是一个硬性要求。

我现在正在设计这个API,我担心安全问题,特别是CSRF。从我对CSRF攻击的基本理解来看,它们由两个重要组件组成:

  1. 能够命名资源和请求体

  2. 欺骗用户/浏览器使用环境认证(如会话)向看起来已经认证的资源发出请求。

修复CSRF攻击的许多经典方法都是基于会话的。由于我的REST API并不真正做会话,这既阻止了很多向量,也阻止了几乎所有修复它们的方法。例如,重复提交是没有意义的,因为没有什么可以重复提交的。

我最初的方法涉及攻击CSRF攻击的第2部分。如果我对所有请求进行身份验证(比如使用HTTP基本身份验证),而浏览器没有保存这些凭据(例如,一些JS发出请求),那么只有拥有凭据的JS才能发出请求,我们就完成了。明显的缺点是应用程序需要知道用户的凭据。另一个不太明显的缺点是,如果我想在API端安全地存储凭据,那么验证密码应该花费固定的、可观的时间。如果安全验证密码需要100毫秒,那么其他每个请求将至少需要100毫秒+ eps,并且需要一些非常聪明的客户端技巧来使其感觉不慢。我可能能够缓存它(因为凭证总是相同的),如果我非常小心,我可能会设法在不引入定时漏洞的情况下做到这一点,但这听起来像是马蜂窝。

OAuth 2.0看起来有点夸张,但我想它可能是最好的解决方案,以免我最终实现得很糟糕。我想我现在可以做HTTP基本认证的事情,当我们有第三方应用程序开发人员时,转移到OAuth。

与OAuth有一点阻抗不匹配。OAuth想要帮助应用访问另一个应用上的东西。我希望用户在这样的帐户存在之前就在其中一个前端注册。

我还考虑过通过使url随机化来攻击第一点——即向查询字符串添加令牌。这当然可以工作,它非常接近于表单中传统的随机令牌的工作方式,并且给定HATEOAS,它甚至应该是相当RESTful的,尽管这提出了两个问题:1)从哪里开始?是否有一个强制的API起始点,您使用HTTP基本认证登录?2)如果应用开发者不能预先预测URL,他们会有多高兴?

我看过如何在RESTful应用程序中防止CSRF ?但是我不同意随机的uri一定是不restful的这一前提。而且,这个问题没有令人满意的答案,也没有提到OAuth。此外,会话双重提交解决方案是无效的,正如我上面提到的(静态前端的域与API端点的域不同)。

我意识到我在这里试图做的基本上是试图允许来自一个域的跨站点请求,而不允许来自另一个域的跨站点请求,这并不容易。肯定会有一些合理的解决方案吧?

CSRF令牌根据定义是"每个用户状态",因此不是RESTful的。出于安全考虑,大多数API都打破了"每个用户状态"的要求,并要求将CSRF令牌作为HTTP头参数传递。

还有其他预防CSRF的方法。检查引用器不如CSRF令牌强,但它是RESTful的,并且VERY不太可能被破坏。请记住,缺少推荐人应被视为请求失败。

XSS可用于绕过基于令牌的CSRF防御和基于引用的CSRF防御。

答案取决于您需要支持什么。如果我们假设你想支持一个web应用程序,其中使用的REST服务,并使用相同的REST服务的API是一些不同的东西,一个恰好是RESTFUL的web应用程序(你可以决定"会话"是为你!).

现在(/me是相当累)我认为你已经建议使用javascript与HTTP基本认证的方式是一个良好的开端。

我有另一个可能的解决方案,所以我将其列为答案。请随意拆开:)

auth.platform.com进行认证并设置cookie。如果auth.site.comauth.platform.com的CNAME,对auth.site.com的请求(在解决后以auth.platform.com结束)是否能够为site.com设置cookie ?这样我就可以重复提交会话cookie。

当然,auth.platform.com只会为少数白名单域名设置cookie。

编辑:当然这根本行不通,因为你必须使用HTTPS来安全地进行身份验证,而HTTPS会看穿你的诡计。

将您的API设计为真正的RESTful API,可以防止最常见的CSRF向量:

  • 避免cookie防止它们被"窃取",
  • 使用GET进行"安全"操作可以防止imgiframes在没有用户交互的情况下触发不安全的操作。

那么你应该实现CORS,让用户的浏览器阻止来自你不信任的来源的请求。