跨站请求伪造 (CSRF) 防御
跨站请求伪造 (CSRF) 可以通过 SameSite
Cookie 和反 CSRF 令牌进行防御。
问题
CSRF 是一种攻击类型,攻击者会通过可信用户向网站发送未经授权的命令。由于它们继承了用户的 Cookie(因此也继承了会话信息),因此它们看起来是有效的命令。CSRF 攻击可能如下所示
<!-- Attempt to delete a user's account -->
<img src="https://accounts.example.org/management/delete?confirm=true" />
当用户访问包含上述 HTML 的页面时,浏览器将尝试向源 URL 发出 GET
请求。如果用户已登录,浏览器将提供其会话 Cookie,并且帐户删除尝试将成功。
解决方案
SameSite
Cookie
SameSite
Cookie 允许您指定您希望浏览器仅在响应来自 Cookie 源站点的请求时才发送 Cookie。例如,这将导致 CSRF 攻击失败,因为恶意命令不会附带 Cookie,因此无法以用户身份进行身份验证。可用的值是
严格
-
导致浏览器仅在响应来自 Cookie 源站点的请求时才发送 Cookie。
宽松
-
与
严格
相似,只是浏览器还会在用户导航到 Cookie 的源站点时发送 Cookie(即使用户来自不同的站点)。 无
-
指定在源请求和跨站点请求中都发送 Cookie。
您应该为您的网站设置尽可能强大的 SameSite
级别,以使其仍然有效。理想情况下,除非您确实需要,否则永远不要设置 无
。请记住,如果未指定标头,则 宽松
是默认值。
反 CSRF 令牌
反 CSRF 令牌通过要求在所有破坏性更改中都存在一个秘密、唯一且不可预测的令牌来防止 CSRF 攻击。这些令牌可以为整个用户会话设置,定期轮换,或者为每个请求唯一创建。
建议您为允许破坏性更改(如帐户删除)的网站使用这两种策略。对于其他网站,反 CSRF 令牌可能不是必需的,尽管仍然建议将 SameSite
设置为非 无
值,以帮助保护用户的 隐私。
大多数应用程序框架都内置了 CSRF 令牌化功能,以简化实施。请务必选择一个具有此功能的框架,不要试图重新造轮子。
示例
实施反 CSRF 令牌以及 SameSite=严格
在帐户删除表单中包含一个秘密的反 CSRF 令牌
<input
type="hidden"
name="csrftoken"
value="1df93e1eafa42012f9a8aff062eeb1db0380b" />
在服务器端,设置反 CSRF Cookie(JavaScript 必须将其发送为 X 标头;它无法跨源执行)
Set-Cookie: CSRFTOKEN=1df93e1eafa42012f9a8aff062eeb1db0380b; Path=/; Secure; SameSite=Strict
回到客户端,使用 JavaScript 将 CSRF 令牌作为 X 标头添加到 XMLHttpRequest
const token = readCookie(CSRFTOKEN); // read the cookie
httpRequest.setRequestHeader("X-CSRF-Token", token); // add it as an X-CSRF-Token header