Appearance
前端攻防安全
概述
前端安全是 Web 应用安全的重要组成部分,涉及 XSS、CSRF、点击劫持等多种攻击方式和防御措施。
常见攻击方式
1. XSS (跨站脚本攻击)
攻击类型
javascript
// 反射型 XSS
// URL: https://example.com?name=<script>alert('XSS')</script>
const name = new URLSearchParams(window.location.search).get('name')
document.body.innerHTML = `Hello ${name}` // 危险!
// 存储型 XSS
// 攻击者提交恶意脚本到数据库,其他用户访问时执行
const comment = '<script>steal(document.cookie)</script>'
saveComment(comment)
// DOM 型 XSS
const input = '<img src=x onerror=alert(1)>'
element.innerHTML = input // 危险!防御措施
javascript
// 1. 输出编码
function escapeHtml(str) {
const escapeMap = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/'
}
return str.replace(/[&<>"'/]/g, char => escapeMap[char])
}
// 使用
element.textContent = userInput // 安全
element.innerHTML = escapeHtml(userInput) // 安全
// 2. CSP (内容安全策略)
// HTTP Header
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com
// HTML Meta
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
// 3. 使用安全的框架
// Vue 自动转义
<template>
<div>{{ userInput }}</div> <!-- 安全 -->
</template>
// React 自动转义
function SafeComponent({ userInput }) {
return <div>{userInput}</div> // 安全
}
// 4. HttpOnly Cookie
// 服务器设置
Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict2. CSRF (跨站请求伪造)
攻击示例
html
<!-- 攻击者网站 -->
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="10000">
</form>
<script>document.forms[0].submit()</script>防御措施
javascript
// 1. CSRF Token
// 服务器生成 Token
const csrfToken = generateCSRFToken()
// 前端请求携带 Token
fetch('/api/transfer', {
method: 'POST',
headers: {
'X-CSRF-Token': csrfToken
},
body: JSON.stringify(data)
})
// 2. SameSite Cookie
Set-Cookie: sessionId=abc123; SameSite=Strict
// 3. 验证 Referer
// 服务器端验证
const referer = request.headers.referer
if (!referer || !referer.startsWith('https://yoursite.com')) {
throw new Error('Invalid referer')
}
// 4. 双重 Cookie 验证
// 将 Token 同时放在 Cookie 和请求参数中
fetch('/api/action', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
...data,
csrf_token: getCookie('csrf_token')
})
})3. 点击劫持
攻击示例
html
<!-- 攻击者网站 -->
<style>
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
</style>
<iframe src="https://bank.com/transfer"></iframe>
<button>点击领取奖品</button>防御措施
javascript
// 1. X-Frame-Options
// HTTP Header
X-Frame-Options: DENY // 禁止所有嵌入
X-Frame-Options: SAMEORIGIN // 只允许同源嵌入
// 2. CSP frame-ancestors
Content-Security-Policy: frame-ancestors 'self' https://trusted.com
// 3. JavaScript 防御
if (window.top !== window.self) {
window.top.location = window.self.location
}
// 或者
<style>body { display: none; }</style>
<script>
if (self === top) {
document.getElementsByTagName('style')[0].innerHTML = ''
} else {
top.location = self.location
}
</script>4. 中间人攻击
防御措施
javascript
// 1. 使用 HTTPS
// 强制 HTTPS
if (location.protocol !== 'https:') {
location.href = 'https:' + window.location.href.substring(window.location.protocol.length)
}
// 2. HSTS
Strict-Transport-Security: max-age=31536000; includeSubDomains
// 3. 证书校验
// 使用证书固定(Certificate Pinning)
// 4. 安全的 Cookie
Set-Cookie: sessionId=abc123; Secure; HttpOnly; SameSite=Strict安全最佳实践
1. 输入验证
javascript
// 前端验证(不能替代后端验证)
function validateInput(input) {
// 白名单验证
const allowedPattern = /^[a-zA-Z0-9_-]+$/
if (!allowedPattern.test(input)) {
throw new Error('Invalid input')
}
// 长度限制
if (input.length > 100) {
throw new Error('Input too long')
}
return input
}
// 使用
const userInput = validateInput(formData.username)2. 安全的 API 调用
javascript
// 使用 HTTPS
const API_BASE = 'https://api.example.com'
// 添加认证头
async function secureFetch(url, options = {}) {
const token = localStorage.getItem('auth_token')
return fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
})
}
// 错误处理
async function apiCall(url, options) {
try {
const response = await secureFetch(url, options)
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return response.json()
} catch (error) {
console.error('API call failed:', error)
throw error
}
}3. 敏感数据处理
javascript
// 不要在前端存储敏感信息
// ❌ 错误
localStorage.setItem('password', password)
localStorage.setItem('credit_card', cardNumber)
// ✅ 正确
// 只存储必要的非敏感信息
localStorage.setItem('user_id', userId)
sessionStorage.setItem('temp_token', tempToken)
// 及时清理
function logout() {
localStorage.removeItem('auth_token')
sessionStorage.clear()
window.location.href = '/login'
}4. 第三方库安全
javascript
// 定期更新依赖
npm audit
npm audit fix
// 检查已知漏洞
npm install -g npm-check-updates
ncu -u
// 使用 SRI (Subresource Integrity)
<script
src="https://cdn.example.com/library.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/ux..."
crossorigin="anonymous"
></script>安全检测工具
1. 自动化扫描
bash
# OWASP ZAP
zap-cli quick-scan https://example.com
# NPM Audit
npm audit
# Snyk
snyk test2. 浏览器安全工具
- Chrome DevTools Security Panel
- Firefox Developer Tools Security
- Web Inspector (Safari)