推荐答案
CSRF 攻击原理
CSRF (Cross-Site Request Forgery,跨站请求伪造) 攻击是指攻击者通过伪装成受信任用户的请求,在用户不知情的情况下,以该用户的身份执行恶意操作。其原理简单来说是:
- 用户登录受信任网站 A,并保持登录状态(例如,cookie 存储了会话信息)。
- 攻击者构造一个恶意请求,该请求的目标是网站 A。
- 用户在登录网站 A 的状态下,访问了攻击者构造的恶意页面或链接。
- 用户的浏览器在不知情的情况下,发送了攻击者构造的恶意请求到网站 A。
- 网站 A 误以为是用户发起的合法请求,从而执行了恶意操作。
CSRF 防御方法
常见的 CSRF 防御方法包括:
- 使用 CSRF Token:
- 服务器在响应中生成一个随机的 token,并将其存储在用户的 session 或 cookie 中。
- 在每个需要保护的表单或 AJAX 请求中,都包含该 token。
- 服务器在接收到请求后,验证请求中的 token 是否与 session 或 cookie 中存储的 token 一致,一致则认为是合法请求,否则拒绝。
- 使用双重 Cookie 验证 (Double Submit Cookie):
- 服务器生成一个随机值,同时将其设置在 HTTP-Only 的 cookie 中和 HTML 的隐藏字段中。
- 客户端发送请求时,隐藏字段的值会被一同发送。
- 服务器接收到请求后,比较 cookie 中的值和请求参数中的值是否一致,一致则认为是合法请求,否则拒绝。
- Referer 检查:
- 服务器检查请求头中的
Referer
字段,判断请求是否来源于合法的域名。 - 注意:
Referer
字段可能被篡改或缺失,因此不推荐作为主要的防御手段。
- 服务器检查请求头中的
- 使用验证码:
- 在敏感操作前,要求用户输入验证码,增加攻击难度。
- SameSite Cookie 属性:
- 设置
SameSite
属性为Strict
或Lax
,可以限制 Cookie 的跨域发送,从而降低 CSRF 攻击风险。 Strict
模式下,只有在访问同域网站时才会发送 Cookie;Lax
模式下,会在 GET 请求(例如,点击链接或表单提交)时发送 Cookie,这在实践中常用。
- 设置
本题详细解读
CSRF 攻击的详细原理
CSRF 的核心在于 “冒充”。攻击者利用用户在目标网站已经建立的信任关系(即登录状态)进行操作。它和 XSS 的区别在于,XSS 利用的是用户对网站的信任,而 CSRF 利用的是网站对用户的信任。
举例说明: 假设有一个银行网站 A,用户登录后可以进行转账操作。
- 用户正常登录网站 A,浏览器存储了网站 A 的 cookie。
- 攻击者创建了一个恶意网站 B,该网站包含一个隐藏的表单或者一个图片链接,该表单或链接的目的地是网站 A 的转账接口,并附带了攻击者指定的转账金额和收款人信息。
- 用户在登录网站 A 的状态下,不小心访问了恶意网站 B。
- 当用户访问恶意网站 B 的时候,浏览器自动发送了恶意请求到网站 A,因为请求会默认携带网站 A 的 cookie,网站 A 无法分辨请求是否来自用户本人。
- 网站 A 以为是用户本人发起的请求,便执行了转账操作。
常见 CSRF 防御方法的详细解读
1. CSRF Token
- 原理: CSRF Token 相当于给每个请求都加上一个“验证码”,只有当验证码匹配时,服务器才允许该请求。
- 实现:
- 服务器在用户登录成功后,为当前会话生成一个随机的、唯一的 token 值。
- 将该 token 值保存到服务器的 Session 中。
- 在页面渲染时,将该 token 值以隐藏字段的形式添加到 HTML 表单中,或者添加到 AJAX 请求的请求头中。
- 当用户提交表单或发送 AJAX 请求时,浏览器会将隐藏字段或请求头中的 token 值一同发送给服务器。
- 服务器接收到请求后,首先检查请求中携带的 token 值是否与服务器存储的 session 中的 token 值一致,如果一致,则表示请求是合法的,否则拒绝处理。
- 优点: 安全性高,能有效防御 CSRF 攻击。
- 缺点: 需要服务器端进行 token 的生成和验证,实现起来稍微复杂。
2. 双重 Cookie 验证
- 原理: 将 token 值同时存储在 cookie 中和请求参数中,服务器比对两者是否一致。
- 实现:
- 服务器在用户登录后,生成一个随机值。
- 将该值通过 HTTP-Only 的 Cookie 发送给客户端。
- 同时,将该值以隐藏字段的形式添加到 HTML 表单中,或通过 JavaScript 动态添加到 AJAX 请求中。
- 客户端提交表单或发送 AJAX 请求时,会将 Cookie 中的值和隐藏字段中的值一同发送给服务器。
- 服务器接收到请求后,会比较 Cookie 中值和请求参数中的值是否一致,一致则认为是合法请求,否则拒绝处理。
- 优点: 实现相对简单,不需要服务器端存储 Session。
- 缺点: 需要通过 JavaScript 获取 Cookie 值,安全性比 CSRF Token 稍低。
3. Referer 检查
- 原理: 通过检查 HTTP 请求头中的
Referer
字段来验证请求的来源。 - 实现:
- 服务器在接收到请求后,检查
Referer
字段的值,如果该值是来源于自己的域名,则认为是合法请求。
- 服务器在接收到请求后,检查
- 优点: 实现简单
- 缺点:
Referer
字段可以被篡改或缺失,且有些浏览器或用户设置可能不发送Referer
字段,因此可靠性不高,不能作为主要的防御手段,通常作为辅助防御手段。
4. 验证码
- 原理: 通过验证码来增加攻击的难度,只有通过验证码校验的请求才会被允许。
- 实现:
- 在敏感操作前,要求用户输入验证码。
- 服务器验证用户输入的验证码是否正确,如果正确,则处理请求。
- 优点: 可以有效防御自动化 CSRF 攻击
- 缺点: 用户体验较差,不适合频繁使用。
5. SameSite Cookie 属性
- 原理: 通过
SameSite
属性来限制 Cookie 的跨域发送,降低 CSRF 攻击的风险。 - 实现:
- 在设置 Cookie 时,添加
SameSite
属性:SameSite=Strict
: 只有在访问同域网站时才会发送 Cookie。SameSite=Lax
: 在 GET 请求(例如,点击链接或表单提交)时发送 Cookie。SameSite=None
: 允许跨域发送,需要配合Secure
属性,仅在 HTTPS 环境下发送。
- 在设置 Cookie 时,添加
- 优点: 可以从根本上阻止某些 CSRF 攻击,实现起来也相对简单。
- 缺点: 需要浏览器支持,并且部分老旧浏览器可能不支持此属性。