您现在的位置是:网站首页 > CSRF 攻击的基本原理文章详情

CSRF 攻击的基本原理

CSRF 攻击的定义与核心逻辑

跨站请求伪造(CSRF)是一种利用用户已登录状态,在用户不知情时以用户名义执行非预期操作的攻击方式。攻击者诱导用户访问恶意页面时,该页面携带伪造请求访问目标站点,由于浏览器会自动携带用户的认证信息(如Cookie),服务器会误认为是用户发起的合法请求。核心逻辑在于跨域请求+身份验证漏洞的组合利用。

典型场景:用户登录银行网站A后未登出,访问恶意网站B,B的页面隐藏了一个向A发起转账的请求,浏览器自动携带A的Cookie完成请求。

攻击的必要条件

  1. 身份验证依赖浏览器自动提交的凭证
    常见于Cookie、Basic Auth等机制,例如:

    // 服务器设置登录态Cookie
    Set-Cookie: sessionid=abc123; HttpOnly; Secure
    
  2. 请求参数可预测
    攻击者能构造出完整请求,如转账接口/transfer?to=attacker&amount=1000的参数结构公开。

  3. 目标站点未校验请求来源
    服务器未验证OriginReferer头,例如:

    POST /transfer HTTP/1.1
    Host: bank.com
    Cookie: sessionid=abc123
    Content-Type: application/x-www-form-urlencoded
    
    to=attacker&amount=1000
    

常见攻击载体与示例

自动提交表单

<!-- 恶意页面隐藏表单 -->
<body onload="document.forms[0].submit()">
  <form action="https://bank.com/transfer" method="POST">
    <input type="hidden" name="to" value="attacker">
    <input type="hidden" name="amount" value="10000">
  </form>
</body>

图片标签GET请求

<!-- 利用img标签自动发送GET请求 -->
<img src="https://bank.com/delete-account?id=123" width="0" height="0">

AJAX请求(受同源策略限制但仍有风险)

// 如果服务器允许任意Origin,仍可能成功
fetch('https://bank.com/change-email', {
  method: 'POST',
  credentials: 'include',
  body: JSON.stringify({email: 'attacker@evil.com'})
});

防御策略的技术实现

同源检测

// 中间件校验Referer头
app.use((req, res, next) => {
  const referer = req.get('Referer');
  if (!referer || !referer.startsWith('https://yourdomain.com')) {
    return res.status(403).send('Invalid request source');
  }
  next();
});

CSRF Token

<!-- 服务端渲染时嵌入Token -->
<form action="/transfer" method="POST">
  <input type="hidden" name="_csrf" value="随机字符串">
  <!-- 其他表单字段 -->
</form>
// 服务端验证示例
app.post('/transfer', (req, res) => {
  if (req.body._csrf !== req.session.csrfToken) {
    return res.status(403).send('CSRF token invalid');
  }
  // 处理正常业务
});

SameSite Cookie属性

Set-Cookie: sessionid=abc123; SameSite=Strict; HttpOnly; Secure

双重Cookie验证

// 前端从Cookie读取token并放入请求头
const token = document.cookie.match(/csrftoken=([^;]+)/)[1];
fetch('/api/action', {
  method: 'POST',
  headers: { 'X-CSRF-TOKEN': token }
});

特殊场景下的防护考量

单页应用(SPA)的Token管理

// 初始加载时获取Token
let csrfToken = '';
fetch('/api/csrf-token', { credentials: 'include' })
  .then(res => res.json())
  .then(data => { csrfToken = data.token; });

// 后续请求携带Token
function safeFetch(url, options) {
  options.headers = {
    ...options.headers,
    'X-CSRF-Token': csrfToken
  };
  return fetch(url, options);
}

文件上传的防护

<!-- 需要为multipart表单单独处理 -->
<form enctype="multipart/form-data">
  <input type="hidden" name="_csrf" value="token">
  <input type="file" name="file">
</form>

历史漏洞案例分析

2018年某社交平台CSRF漏洞导致用户关系被篡改,攻击者构造如下页面:

<script>
  function exploit() {
    fetch('https://social.com/api/follow', {
      method: 'POST',
      credentials: 'include',
      body: JSON.stringify({userId: 'attacker'})
    });
  }
  setTimeout(exploit, 3000);
</script>

漏洞成因:API未校验Content-Type为application/json的请求来源,且未使用CSRF Token。

与其他安全机制的协同

与CORS策略的关系

Access-Control-Allow-Origin: https://trusted.com
Access-Control-Allow-Credentials: true

即使正确配置CORS,仍需CSRF防护,因为:

  1. 简单请求(GET/POST表单)不触发预检
  2. 恶意页面可能通过表单而非AJAX发起请求

与XSS防护的关联

Set-Cookie: sessionid=abc123; HttpOnly; Secure; SameSite=Strict

XSS漏洞可能导致CSRF Token被窃取,因此必须配合内容安全策略(CSP):

Content-Security-Policy: script-src 'self'

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步