如何防范CSRF漏洞
翻译
原文:https://portswigger.net/web-security/csrf/preventing
- name: 翻译
desc: 原文:https://portswigger.net/web-security/csrf/preventing
bgColor: '#F0DFB1'
textColor: 'green'
2
3
4
# 如何防范CSRF漏洞
在本节中,我们将提供一些高级指导,有关于如何保护你自己的网站免受各种 CSRF 漏洞的影响,就像实验室中演示的那样。
# 1使用CSRF token
(((译者加:有关于 “熵” 的信息可参阅这篇文章 (opens new window))))
防御 CSRF 攻击的最可靠方法是,在相关请求中包含 CSRF 令牌。令牌必须满足以下条件:
- 具有高熵的不可预测性,一般而言,会话(session)令牌也是如此。
- 绑定到用户的会话。
- 在执行相关操作之前,对每种情况都进行严格验证。
# 1.1如何生成CSRF token?
CSRF 令牌应该包含显著的熵,并且具有很强的不可预测性,与一般的会话令牌具有相同的属性。
你应该使用密码安全的伪随机数生成器(CSPRNG),该生成器在创建时,使用时间戳 和 静态密钥作为种子。
如果你需要超出 CSPRNG 强度的进一步保证,你可以通过将其输出 与 一些用户特定的熵连接起来,从而生成单个令牌,并对整个结构进行强哈希。对于一些试图 基于给定令牌样本 来分析令牌结构的攻击者来说,这提供了额外的阻碍。
# 1.2如何传输CSRF token?
CSRF 令牌应被视为机密,并在其整个生命周期中,以安全的方式进行处理。通常有效的方法是,在 HTML 表单的隐藏字段中包含令牌,并通过POST
方法将令牌传输到客户端。然后,提交表单时,令牌将作为请求参数包含在内:
<input type="hidden" name="csrf-token" value="CIwNZNlR4XbisJF39I8yWnWX9wX4WFoz" />
为了提高安全性,包含 CSRF 令牌的字段应尽可能早地放置在 HTML 文档中,理想情况下,放在任何非隐藏输入字段之前,以及在 HTML 中嵌入用户可控数据的任何位置之前。这缓解了攻击者使用精心构造的数据来操纵 HTML 文档,并捕获其部分内容的各种技术。
另一种方法是,将令牌放入 URL 查询字符串中,但安全性较低,因为查询字符串会:
- 记录在客户端和服务器端的不同位置;
- 有可能在HTTP Referer标头中传输给第三方;
- 可以在用户的浏览器中显示在屏幕上。
某些应用程序在自定义请求标头中传输 CSRF 令牌。对于一些设法 预测或捕获其他用户令牌 的攻击者来说,这提供了进一步的防御,因为浏览器通常不允许跨域发送自定义标头。但是,这种方法将应用程序限制为使用 XHR(而不是 HTML 表单)发出受 CSRF 保护的请求,并且在许多情况下 可能会被认为过于复杂。
CSRF 令牌不应在 Cookie 中传输。
# 2使用严格的SameSite cookie限制
除了实现强大的 CSRF 令牌验证之外,我们还建议你对发布的每个 Cookie 都明确设置你自己的 SameSite 限制。这样一来,你可以准确控制 Cookie 将在哪些上下文中使用,而不管浏览器如何。
将来,即使所有浏览器最终都采用 “默认Lax(宽松)” 策略,但这也并不适用于每个 Cookie,并且和Strict
(严格)级别的限制比起来,这更容易被绕过。同时,由于不同浏览器之间的不一致性,意味着只有一部分用户会受益于任何 SameSite 保护。
理想情况下,你应该默认使用Strict
策略,然后仅在有充分理由时,才将其降低到Lax
。切勿使用SameSite=None
来禁用 SameSite 限制,除非你完全了解安全隐患。
# 3警惕跨源、同站攻击
尽管正确配置的 SameSite 限制可以很好地抵御跨站点攻击,但重要的是必须要了解,它们对跨源、同站攻击完全无能为力。
如果可以,我们建议将不安全的内容(例如用户上传的文件)与 任何敏感功能或数据 隔离在单独的网站上。在测试站点时,请务必彻底审核 属于同一站点的所有可用攻击面,包括其任何同级域。