前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • HTTP

    • 基础篇

      • HTTP的前世今生
      • HTTP是什么
      • HTTP世界全览
      • HTTP分层
      • 键入网址到回车发生什么
      • HTTP报文是什么样子的
      • 理解请求方法
      • URI
      • 响应状态码
      • HTTP有哪些特点
      • HTTP优缺点
      • HTTP的实体数据
      • HTTP传输大文件
      • HTTP的连接管理
      • HTTP的重定向
      • HTTP的Cookie机制
      • HTTP的缓存控制
      • HTTP的代理服务
      • HTTP的缓存代理
    • 高级篇

    • 扩展篇

  • 浏览器相关

  • 计算机基础

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

CSRF攻击:陌生链接不要随便点|浏览器篇

# CSRF攻击:陌生链接不要随便点

30 秒速记

  • CSRF 利用用户已经建立的登录状态,诱导浏览器向受信任站点发起并非用户真实意图的操作请求。
  • 攻击链成立的关键是浏览器中仍保存目标站点的 Cookie、Session 等认证状态,恶意页面借此让请求以受害者身份被处理。
  • 案例中的恶意页面调用 Gmail 的 HTTP 设置接口创建邮件转发过滤器,随后攻击者利用获得的邮件完成域名账户密码重置和转移。
  • CSRF 的直接目标是借用用户身份执行操作;XSS 则是在页面中注入恶意脚本并窃取或操纵页面数据,两者攻击入口不同。
  • 点击陌生链接只是触发方式之一;真正的风险来自目标接口接受了携带既有登录状态、但违背用户意图的请求。

CSRF 是攻击者借用用户已有的登录状态,诱导浏览器向受信任站点提交违背用户真实意图的操作请求。 攻击者通常不需要看到登录 Cookie,只要浏览器按规则自动携带它,而服务端又没有验证请求意图,敏感操作就可能被当成用户本人发起。案例中恶意页面创建了 Gmail 邮件转发规则,攻击者再利用邮件完成密码重置和域名转移。陌生链接只是触发方式之一,防护重点仍是 CSRF Token、请求来源校验和合理的 SameSite 配置。

中我们讲到了 XSS 攻击,XSS 的攻击方式是黑客往用户的页面中注入恶意脚本,然后再通过恶意脚本将用户页面的数据上传到黑客的服务器上,最后黑客再利用这些数据进行一些恶意操作。XSS 攻击能够带来很大的破坏性,不过另外一种类型的攻击也不容忽视,它就是我们今天要聊的 CSRF 攻击。

相信你经常能听到的一句话:“别点那个链接,小心有病毒!”点击一个链接怎么就能染上病毒了呢?

我们结合一个真实的关于 CSRF 攻击的典型案例来分析下,在 2007 年的某一天,David 无意间打开了 Gmail 邮箱中的一份邮件,并点击了该邮件中的一个链接。过了几天,David 就发现他的域名被盗了。不过几经周折,David 还是要回了他的域名,也弄清楚了他的域名之所以被盗,就是因为无意间点击的那个链接。

那 David 的域名是怎么被盗的呢?

我们结合下图来分析下 David 域名的被盗流程:

  • 首先 David 发起登录 Gmail 邮箱请求,然后 Gmail 服务器返回一些登录状态给 David 的浏览器,这些信息包括了 Cookie、Session 等,这样在 David 的浏览器中,Gmail 邮箱就处于登录状态了。
  • 接着黑客通过各种手段引诱 David 去打开他的链接,比如 hacker.com,然后在 hacker.com 页面中,黑客编写好了一个邮件过滤器,并通过 Gmail 提供的 HTTP 设置接口设置好了新的邮件过滤功能,该过滤器会将 David 所有的邮件都转发到黑客的邮箱中。
  • 最后的事情就很简单了,因为有了 David 的邮件内容,所以黑客就可以去域名服务商那边重置 David 域名账户的密码,重置好密码之后,就可以将其转出到黑客的账户了。

以上就是 David 的域名被盗的完整过程,其中前两步就是我们今天要聊的 CSRF 攻击。David 在要回了他的域名之后,也将整个攻击过程分享到他的站点上了,如果你感兴趣的话,可以参考

原理拆解: 攻击者通常看不到受害者的登录 Cookie,但这并不妨碍浏览器在符合 Cookie 发送规则时自动携带它。恶意页面只负责构造对受信任站点的请求,目标服务器看到有效会话后便把请求识别成受害者;若敏感接口没有额外验证请求意图,修改邮箱转发规则、变更绑定信息等操作就会成功。后续的密码重置和域名转移属于业务后果,并不是 CSRF 请求本身。

最小验证: 输入是一台本地服务和浏览器对 /transfer 的请求,要验证仅有会话 Cookie 时会被拒绝,同时具备会话与 CSRF Token 才能修改状态。将代码保存为 csrf-demo.js,用 node csrf-demo.js 启动后访问 http://localhost:3000/。

const http = require('http');

http.createServer((req, res) => {
  if (req.url === '/') {
    res.writeHead(200, {
      'Content-Type': 'text/html; charset=utf-8',
      'Set-Cookie': 'sid=alice; HttpOnly; SameSite=Lax'
    });
    return res.end(`<form method="POST" action="/transfer">
      <input name="csrf" value="token-123">
      <button>提交转账</button>
    </form>`);
  }
  if (req.method === 'POST' && req.url === '/transfer') {
    let body = '';
    req.on('data', chunk => body += chunk);
    return req.on('end', () => {
      const loggedIn = (req.headers.cookie || '').includes('sid=alice');
      const validToken = new URLSearchParams(body).get('csrf') === 'token-123';
      res.writeHead(loggedIn && validToken ? 200 : 403);
      res.end(loggedIn && validToken ? 'transfer accepted' : 'forbidden');
    });
  }
  res.writeHead(404).end();
}).listen(3000, () => console.log('http://localhost:3000/'));
@前端进阶之旅: 代码已经复制到剪贴板

表单正常提交时预期得到 transfer accepted;删除隐藏值或用不含令牌的表单提交时得到 forbidden。示例令牌为固定值,仅用于展示校验链路,生产系统应生成不可预测且绑定会话的令牌。

边界与排查: SameSite 能降低跨站携带 Cookie 的概率,但旧客户端、错误属性和特定跳转链路可能削弱保护,不能代替服务端校验。XSS 若已能读取页面或代替用户调用接口,也可能绕过页面中的令牌防线。排查时应核对敏感接口是否拒绝无令牌请求,并检查 Origin、Referer、Cookie 属性、审计日志及状态变更记录。

面试官追问

追问 1用户已登录邮箱后只打开了 hacker.com,既没输入密码也没把 Cookie 发给攻击者,邮件转发规则为什么仍可能被改?
参考回答

攻击者不必读取 Cookie,只需诱导浏览器向邮箱设置接口构造请求,浏览器可能按规则自动携带现有登录状态。若服务端只认会话而不验证请求意图,就会把恶意操作当成用户本人提交。

追问 2代码评审发现 /transfer 只检查 sid 登录 Cookie,前端表单没有 CSRF Token,你会要求服务端怎样改?
参考回答

服务端应让状态变更请求同时通过会话检查和不可预测、与会话绑定的 CSRF Token 校验,无令牌或令牌错误时返回拒绝。不能只在页面上隐藏按钮,因为攻击页面仍可直接构造请求。

追问 3产品把登录 Cookie 设置成 SameSite=Lax 后准备删除全部服务端令牌校验,理由是现代浏览器不会跨站携带,你会同意吗?
参考回答

不应把 SameSite 当作服务端校验的完全替代,它只能降低部分跨站携带 Cookie 的概率。旧客户端、属性配置错误或特定跳转链路可能削弱保护,因此敏感操作仍应保留令牌及来源检查。

追问 4线上出现一批异常邮箱转发规则,但访问日志都带有效会话,安全值班会从哪些证据判断是否为 CSRF?
参考回答

应检查敏感接口是否接受无 CSRF Token 请求,并核对 Origin、Referer、Cookie 属性、审计日志和状态变更时间线。有效会话不能排除 CSRF,因为攻击本就借用受害者已有的登录状态。

追问 5安全团队在“只校验 Origin”与“会话绑定令牌加来源检查”之间争论,涉及账户绑定变更时你会选哪种?
参考回答

应以会话绑定的不可预测令牌作为核心校验,并把 Origin、Referer 作为额外排查或防护信号。单一来源头可能受客户端行为和部署配置影响;组合方案实现成本更高,但对敏感状态变更更稳妥。

追问 6一次事故里脚本读取页面数据后外传,另一次则借已登录状态修改 /transfer,面试时你会怎样区分 XSS 与 CSRF?
参考回答

读取页面数据并外传符合 `XSS的利用路径,而借浏览器现有身份触发跨站状态变更符合CSRF。两者可能相互影响:若 XSS`` 已能读取页面或代替用户请求,它也可能绕过页面中的令牌防线。

# 什么是 CSRF 攻击

30 秒速记

  • CSRF 是攻击者借用用户已有的登录状态,向目标服务器伪造非用户本意的跨站请求。
  • 攻击成立的关键是用户仍处于登录状态,并访问了攻击者控制或布置的第三方页面。
  • 恶意页面可以触发自动 GET、自动 POST,也可以诱导用户主动点击请求链接。
  • 服务器若只根据登录凭证确认身份,却不判断请求是否代表用户真实意愿,就可能执行转账等敏感操作。
  • CSRF 不要求把恶意代码注入目标页面;它利用的是目标接口的校验缺口和用户现存的登录状态。

CSRF 是攻击者借用用户已有的登录状态,通过第三方页面伪造非用户本意的跨站请求。 本质上是浏览器自动带上目标站点认可的身份凭证,而服务器只确认了“你是谁”,没有确认“这是不是你的真实意愿”。比如用户登录网银后打开恶意页面,页面可能自动发起 GET、提交 POST,或者诱导用户点击转账链接。它不需要向目标页面注入代码;CORS 也不能单独防住,因为它主要限制读取跨源响应,而不是阻止请求发出。

← 跨站脚本攻击XSS:为什么cookie中有httpOnly属性沙盒:页面和系统之间的隔离墙 →

fe
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • HTTP

    • 基础篇

      • HTTP的前世今生
      • HTTP是什么
      • HTTP世界全览
      • HTTP分层
      • 键入网址到回车发生什么
      • HTTP报文是什么样子的
      • 理解请求方法
      • URI
      • 响应状态码
      • HTTP有哪些特点
      • HTTP优缺点
      • HTTP的实体数据
      • HTTP传输大文件
      • HTTP的连接管理
      • HTTP的重定向
      • HTTP的Cookie机制
      • HTTP的缓存控制
      • HTTP的代理服务
      • HTTP的缓存代理
    • 高级篇

    • 扩展篇

  • 浏览器相关

  • 计算机基础