最近我在学习Web安全的一些基础知识,但有些东西我无法理解。反CSRF代币如何在SPA-API通信中工作?
据我所知,反CSRF用于SPA-API通信,如下所示;
- 浏览器向API发送登录请求
- API服务器生成一个令牌并将其发送回浏览器
- 浏览器存储它,当浏览器发出下一个请求时,令牌将与一起发送
- API可以确保请求来自真正的前端,因为它包含令牌
我突然想到一个问题——它如何预防CSRF?如果令牌存储在cookie中,则每当请求发生时,它将自动发送到API,就像通常的会话cookie一样。即使它存储在其他存储中(如会话存储或本地存储(,也可以使用JavaScript进行访问。
因此,一旦用户被攻击者的网站吸引,反CSRF代币就完全无用了。
最重要的是,我不明白反CSRF令牌和身份验证/授权中使用的常见cookie之间有什么区别……
也许我对反CSRF令牌的工作方式产生了严重的误解。请指出它出了什么问题。
当攻击者可以使用经过身份验证的用户的cookie向端点提交请求时,就会存在最常见的CSRF漏洞之一。如果您不使用cookie(即验证用户的请求(或其他自动验证技术(如HTTP基本验证(,则通常不需要CSRF令牌。
示例#1:
假设您使用的是REST API,它依赖于访问令牌或承载令牌进行身份验证。此令牌通常在HTTP授权标头(而不是cookie(中提交。在这种情况下,只要身份验证不是自动的(例如,使用cookie(,就不需要CSRF令牌。
示例#2:
在这种情况下,假设浏览器确实将会话cookie发送到web服务/API以验证请求。那么,是的,如果不实施反CSRF控制,你将很容易受到CSRF的影响。防止这种情况的一种方法是在加载SPA时向浏览器提供反CSRF令牌。然后,浏览器可以将该令牌与请求一起发送到端点。然后,当收到请求时,web服务必须验证该令牌。
这种验证可以通过多种方式进行。这可以使用双重提交cookie、cookie到标头令牌、加密技术,甚至共享数据库来完成。
使用反CSRF令牌:
反CSRF代币通常应而不是存储在cookie中。如OWASP CSRF预防作弊表所述:
<meta>
标签中可以包含CSRF令牌。所有后续呼叫可以从该CCD_ 2标签中提取CSRF令牌。它可以也可以存储在JavaScript变量中或DOM上的任何位置。但是,不建议将其存储在cookie或本地浏览器中存储
例如,反CSRF令牌可能会嵌入页面中,如下所示:
<meta name="csrf-token" content="{{ csrf_token() }}">
其中csrf_token()
调用一些将令牌嵌入标记中的服务器端函数。
然后可以使用在JavaScript中读取
let csrf_token = document.querySelector("meta[name='csrf-token']").getAttribute("content");
然后在做出API请求时(例如,在POST请求中的X-CSRF-Token
报头中(发送到服务器。此外,令牌对于会话应该是唯一的。
然而,即使令牌要存储在cookie中,也可以使用HttpOnly标头设置cookie。这样可以防止JavaScript读取cookie。这在减轻跨站点脚本(XSS(攻击方面更为有用。
附加信息:
- 这个StackExchange安全问题包含了许多关于在RESTAPI中使用CSRF保护的好信息
关于CSRF的其他良好资源:
- https://portswigger.net/web-security/csrf
- https://owasp.org/www-community/attacks/csrf