是否有必要同源来防止CSRF(我知道这还不够(? 或者可以在没有任何同源策略的情况下完成?这适用于客户端呈现的应用程序,我无法在页面上的元素中隐藏令牌。
下面是CSRF攻击的典型示例:
您- 登录到银行网站,现在您有一个会话cookie来保持登录状态。
- 您访问一个恶意站点,该站点向
/transfer_funds
发送 POST 请求。 - 这些 Cookie 与 POST 请求一起发送。
- 请求已通过身份验证,现在您的钱已发送给攻击者。
现在,让我们看看每一步,看看如何预防它们。
第 1 步可以通过没有登录 cookie 来阻止,但这非常不方便且不切实际。
第 2 步可以通过非常小心您访问的网站来防止,但这也非常不方便,您无法保证您的用户这样做。您可能认为 CORS 策略可能会有所帮助,但事实并非如此,因为有多种方法可以绕过它。fetch
API 具有忽略 CORS 标头的no-cors
模式,并且只是不使响应可用,但在这种情况下,攻击者不关心响应,只关心请求。此外,另一个常见的事情是使用 javascript 填写表单,然后使用 javascript 提交表单,也绕过 CORS。
可以使用 cookie 的SameSite
属性绕过第 3 步,特别是Lax
或Strict
。对于Lax
,cookie 仅在第三方请求时发送,如果它是 GET 请求,并且您的网站应该设计为没有 GET 请求可以做任何坏事。对于Strict
,第三方网站根本无法发送cookie,这意味着他们甚至无法利用GET请求。这可能是最好的解决方案,大多数浏览器默认使用SameSite=Lax
,这意味着CSRF不是一个主要问题。如果您想确保您的用户安全,您可以在 Cookie 上明确设置SameSite=Lax
或SameSite=Strict
。
使用经典的 CSRF 令牌 + CORS 可以防止第 4 步,这要求攻击者发出 GET 请求以获取 CSRF 令牌,然后才能发出 POST 请求。但是,由于他们现在实际上需要响应,因此no-cors
不起作用,并且无法以您的身份进行身份验证。
另外,作为旁注,如果你根本没有cookie,那么CSRF不是问题。
是的,但有开销。
成功登录后颁发令牌。由于您没有在页面上来回传递它,因此有必要在服务器上使用一些后端存储(例如会话状态(将其与登录用户的会话相关联。这是开销。
现在,每次调用可以更改状态的 API 都必须包含令牌,例如在标头中。令牌可以缓存在客户端上。没有令牌,无法访问任何更改状态的内容。
恭喜,您已经击败了 CSRF 攻击。您仍然需要处理所有常见的管理方面,例如令牌过期、令牌续订等。