阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > CSRF 攻击的典型场景

CSRF 攻击的典型场景

作者:陈川 阅读数:30231人阅读 分类: 前端安全

CSRF(Cross-Site Request Forgery)攻击是一种利用用户已登录的身份,在用户不知情的情况下执行非预期操作的攻击方式。攻击者通过伪造请求,诱骗用户或浏览器发送恶意请求,从而绕过身份验证机制。

CSRF 攻击的基本原理

CSRF 攻击的核心是利用浏览器的自动携带 Cookie 机制。当用户登录某个网站后,浏览器会存储会话 Cookie,并在后续请求中自动附加这些 Cookie。攻击者通过构造一个恶意页面或链接,诱导用户访问,从而触发一个跨站请求。由于请求携带了用户的合法 Cookie,服务器会误认为是用户主动发起的操作。

典型的攻击流程如下:

  1. 用户登录可信网站 A,并保存了会话 Cookie。
  2. 用户未退出登录的情况下访问恶意网站 B。
  3. 网站 B 的页面中包含一个向网站 A 发起请求的代码(如表单或脚本)。
  4. 浏览器自动携带网站 A 的 Cookie 发送请求,网站 A 服务器认为这是用户合法操作。

典型攻击场景示例

场景一:通过 GET 请求修改数据

假设一个银行网站的转账功能使用 GET 请求实现,URL 如下:

https://bank.example/transfer?to=attacker&amount=1000

攻击者可以在恶意网站中嵌入一个图片标签:

<img src="https://bank.example/transfer?to=attacker&amount=1000" width="0" height="0">

当用户访问该页面时,浏览器会自动加载图片,并发送 GET 请求完成转账。

场景二:通过表单提交伪造请求

如果银行改用 POST 请求,但未防护 CSRF,攻击者可构造一个隐藏表单:

<form action="https://bank.example/transfer" method="POST">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="1000">
</form>
<script>document.forms[0].submit();</script>

用户访问页面时,表单会自动提交。

场景三:利用 JSON API 的 CSRF

现代应用常用 JSON API,但若未正确配置 CORS,仍可能被攻击。例如:

fetch('https://api.example/change-email', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'attacker@example.com' }),
  credentials: 'include' // 自动携带 Cookie
});

攻击者可通过恶意页面直接发送该请求。

高危操作与敏感接口

以下类型的接口极易成为 CSRF 攻击目标:

  • 修改用户信息(密码、邮箱、手机号)
  • 资金操作(转账、支付)
  • 数据删除(清空购物车、删除账号)
  • 权限变更(提升用户角色)

例如,社交网站的“删除账号”接口:

POST /api/account/delete HTTP/1.1

只需一个简单的伪造请求即可导致账号被删。

防御措施的实现细节

同源检测:Origin 与 Referer 校验

服务器端应验证请求头中的 OriginReferer

// Node.js 示例
app.post('/transfer', (req, res) => {
  const origin = req.get('Origin');
  if (origin !== 'https://yourdomain.com') {
    return res.status(403).send('Forbidden');
  }
  // 处理正常逻辑
});

CSRF Token 机制

  1. 生成 Token
// 服务端生成并存储 Token
const csrfToken = crypto.randomBytes(32).toString('hex');
session.csrfToken = csrfToken;
  1. 前端携带 Token
<form action="/transfer" method="POST">
  <input type="hidden" name="_csrf" value="<%= csrfToken %>">
  <!-- 其他表单字段 -->
</form>
  1. 服务端验证
app.post('/transfer', (req, res) => {
  if (req.body._csrf !== session.csrfToken) {
    return res.status(403).send('Invalid CSRF token');
  }
  // 处理正常逻辑
});

SameSite Cookie 属性

设置敏感 Cookie 的 SameSite 属性:

Set-Cookie: sessionId=abc123; SameSite=Strict; Secure; HttpOnly
  • Strict:完全禁止第三方 Cookie
  • Lax:允许安全方法(如 GET)的跨站请求

双重 Cookie 验证

  1. 前端从 Cookie 读取 token:
function getCookie(name) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop().split(';').shift();
}
const csrfToken = getCookie('csrfToken');
  1. 在请求头中附加:
fetch('/api/transfer', {
  method: 'POST',
  headers: {
    'X-CSRF-TOKEN': csrfToken
  }
});

框架内置防护机制

Express 的 csrf 中间件

const csrf = require('csurf');
app.use(csrf({ cookie: true }));

// 在视图中注入 token
app.get('/form', (req, res) => {
  res.render('form', { csrfToken: req.csrfToken() });
});

Django 的 CSRF 防护

模板中自动添加 token:

<form method="post">
  {% csrf_token %}
  <!-- 表单内容 -->
</form>

Spring Security 配置

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
  }
}

特殊场景下的防护

单页应用(SPA)的 CSRF 防护

对于前后端分离架构:

  1. 服务端设置 SameSite=Lax 的 Cookie
  2. 前端从首次响应中获取 CSRF Token:
// 登录响应示例
{
  "user": {...},
  "csrfToken": "a1b2c3d4"
}
  1. 后续请求在 Header 中携带:
axios.defaults.headers.common['X-CSRF-Token'] = storedCsrfToken;

文件上传的 CSRF 防护

传统表单上传需特殊处理:

<form enctype="multipart/form-data">
  <input type="hidden" name="_csrf" value="token">
  <input type="file" name="file">
</form>

防御措施的局限性

  • Token 泄露:若存在 XSS 漏洞,攻击者可窃取 Token
  • 子域名风险:同站但不同子域可能共享 Cookie
  • 浏览器兼容性:旧版浏览器可能不支持 SameSite

实际案例分析

案例 1:社交媒体关注劫持

某平台关注 API 未防护 CSRF:

POST /api/follow HTTP/1.1
Host: social.example
Cookie: session=valid_session

{"userId":"attacker"}

攻击者构造页面自动发送该请求,导致用户关注恶意账号。

案例 2:电商平台价格篡改

商品修改接口缺少防护:

fetch('/admin/products/123', {
  method: 'PUT',
  body: JSON.stringify({ price: 0.01 })
});

攻击者可诱骗管理员访问恶意页面篡改商品价格。

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌