前端安全

前端安全

核心威胁(6大类型)

记忆口诀:XSS → CSRF → 点击劫持 → SQL注入 → 中间人攻击 → 其他

1
2
3
4
5
6
1. XSS(跨站脚本攻击):注入恶意脚本
2. CSRF(跨站请求伪造):伪造用户请求
3. 点击劫持:诱导用户点击
4. SQL注入:注入恶意SQL
5. 中间人攻击:拦截篡改数据
6. 其他:DDoS、暴力破解等

1. XSS(Cross-Site Scripting)跨站脚本攻击

1.1 XSS攻击类型

存储型XSS(最危险)

1
2
3
4
5
6
7
8
9
10
11
12
// 攻击场景:评论、留言板
// 1. 攻击者提交恶意脚本到数据库
const comment = '<script>alert(document.cookie)</script>';

// 2. 其他用户访问页面时,脚本被执行
<div>{comment}</div> // 直接渲染,脚本执行

// 危害:
// - 窃取Cookie
// - 劫持用户会话
// - 篡改页面内容
// - 钓鱼攻击

反射型XSS

1
2
3
4
5
6
// 攻击场景:URL参数
// 1. 攻击者构造恶意URL
https://example.com/search?q=<script>alert(document.cookie)</script>

// 2. 服务器直接返回参数内容
<div>搜索结果:{query}</div> // 脚本执行

DOM型XSS

1
2
3
// 攻击场景:前端直接操作DOM
const hash = location.hash.slice(1);
document.getElementById('content').innerHTML = hash; // 脚本执行

1.2 XSS防御方案

方案1:输出转义(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// HTML转义
function escapeHtml(str) {
const map = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;',
'/': '&#x2F;'
};
return str.replace(/[&<>"'/]/g, (char) => map[char]);
}

// React自动转义
<div>{userInput}</div> // 自动转义,安全

// ❌ 危险用法
<div dangerouslySetInnerHTML={{ __html: userInput }} />

方案2:CSP(Content Security Policy)

1
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.com

方案3:HttpOnly Cookie

1
Set-Cookie: sessionId=xxx; HttpOnly; Secure; SameSite=Strict

2. CSRF(Cross-Site Request Forgery)跨站请求伪造

2.1 CSRF攻击原理

1
2
3
// 恶意网站B的代码
<img src="https://bank.com/transfer?to=hacker&amount=10000">
// 浏览器会自动带上Cookie,请求成功

2.2 CSRF防御方案

方案1:CSRF Token(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 服务端生成Token
const csrfToken = generateRandomToken();
res.cookie('csrfToken', csrfToken);

// 前端请求时携带Token
axios.post('/api/transfer', data, {
headers: {
'X-CSRF-Token': getCookie('csrfToken')
}
});

// 服务端验证
if (req.body.csrfToken !== req.cookies.csrfToken) {
return res.status(403).send('CSRF token invalid');
}

方案2:SameSite Cookie

1
Set-Cookie: sessionId=xxx; SameSite=Strict

方案3:验证Referer/Origin

1
2
3
if (!referer || !referer.startsWith('https://trusted.com')) {
return res.status(403).send('Invalid referer');
}

3. 点击劫持(Clickjacking)

3.1 防御方案

X-Frame-Options(推荐)

1
2
X-Frame-Options: DENY           // 禁止被iframe嵌入
X-Frame-Options: SAMEORIGIN // 只允许同源嵌入

CSP frame-ancestors

1
Content-Security-Policy: frame-ancestors 'none'

4. SQL注入

4.1 防御方案

参数化查询(推荐)

1
2
3
4
const sql = 'SELECT * FROM users WHERE username=? AND password=?';
db.query(sql, [username, password], (err, results) => {
// 安全
});

5. 中间人攻击(MITM)

5.1 防御方案

HTTPS(必须)

1
2
3
4
5
6
7
8
9
10
// 强制使用HTTPS
app.use((req, res, next) => {
if (req.protocol !== 'https') {
return res.redirect('https://' + req.hostname + req.url);
}
next();
});

// HSTS
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

6. 其他安全威胁

敏感信息泄露

1
2
3
4
5
// ❌ 不要在前端存储敏感信息
localStorage.setItem('password', '123456'); // 危险

// ✅ 使用Token,设置过期时间
localStorage.setItem('token', 'xxx');

文件上传漏洞

1
2
3
4
5
6
7
8
// 1. 验证文件类型
const allowedTypes = ['image/jpeg', 'image/png'];
if (!allowedTypes.includes(file.mimetype)) {
return res.status(400).send('Invalid file type');
}

// 2. 验证文件大小
const maxSize = 5 * 1024 * 1024; // 5MB

DDoS防御

1
2
3
4
5
6
7
// 限流
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
message: 'Too many requests'
});
app.use('/api/', limiter);

7. 面试口述版本

面试官:请说说前端常见的安全问题及防御方案

回答框架:

“前端主要面临6类安全威胁:

1. XSS(跨站脚本攻击)

  • 攻击者注入恶意脚本,窃取Cookie、劫持会话
  • 防御:输出转义、CSP策略、HttpOnly Cookie、使用DOMPurify

2. CSRF(跨站请求伪造)

  • 攻击者伪造用户请求,执行恶意操作
  • 防御:CSRF Token、SameSite Cookie、验证Referer

3. 点击劫持

  • 透明iframe覆盖,诱导用户点击
  • 防御:X-Frame-Options、CSP frame-ancestors

4. SQL注入

  • 注入恶意SQL,绕过验证或窃取数据
  • 防御:参数化查询、输入验证、ORM框架

5. 中间人攻击

  • 拦截、篡改通信数据
  • 防御:HTTPS、HSTS、证书验证

6. 其他威胁

  • 敏感信息泄露:不在前端存储密码、密钥
  • 文件上传漏洞:验证类型、大小、重命名
  • DDoS攻击:限流、验证码、CDN

安全原则:

  • 永远不信任用户输入
  • 最小权限原则
  • 纵深防御(多层防护)
  • 定期安全审计”

8. 高频追问

Q1: XSS和CSRF的区别?

特性 XSS CSRF
攻击方式 注入恶意脚本 伪造用户请求
攻击目标 用户浏览器 服务器
是否需要登录 不需要 需要
利用的是 用户对网站的信任 网站对用户的信任
防御重点 输出转义 Token验证

Q2: 如何防止XSS攻击?

输出转义(最重要):

  • 使用框架自动转义(React、Vue)
  • 手动转义HTML特殊字符
  • 避免使用dangerouslySetInnerHTML、v-html

CSP策略:

  • 限制脚本来源
  • 禁止内联脚本

HttpOnly Cookie:

  • JS无法访问Cookie
  • 防止Cookie被窃取

Q3: CSRF Token的原理?

1
2
3
4
5
6
7
1. 服务器生成随机Token,存储在Session
2. 前端请求时携带Token(请求头或请求体)
3. 服务器验证Token是否匹配

为什么有效?
- 攻击者无法获取Token(同源策略)
- 伪造的请求没有Token,会被拒绝

Q4: SameSite Cookie有哪些值?

1
2
3
4
5
6
7
8
9
10
11
SameSite=Strict
- 完全禁止第三方Cookie
- 最安全,但可能影响用户体验

SameSite=Lax(默认)
- 部分禁止第三方Cookie
- GET请求允许,POST请求禁止

SameSite=None
- 不限制第三方Cookie
- 必须配合Secure(HTTPS)

Q5: 如何安全地存储Token?

方案对比:

存储方式 优点 缺点 适用场景
LocalStorage 持久化、容量大 易受XSS攻击 低敏感度
Cookie 可设置HttpOnly 易受CSRF攻击 需要防CSRF
Memory 最安全 刷新丢失 高敏感度

推荐方案:

1
2
3
4
5
6
7
// Token存Cookie(HttpOnly)
Set-Cookie: accessToken=xxx; HttpOnly; Secure; SameSite=Strict

// 前端无需存储Token,由浏览器自动携带
fetch('/api/data', {
credentials: 'include'
});

Q6: HTTPS的工作原理?

1
2
3
4
5
6
7
8
9
10
11
12
1. 客户端发起HTTPS请求
2. 服务器返回SSL证书(包含公钥)
3. 客户端验证证书有效性
4. 客户端生成随机密钥,用公钥加密发送
5. 服务器用私钥解密,获得密钥
6. 双方使用密钥进行对称加密通信

为什么安全?
- 非对称加密交换密钥(RSA)
- 对称加密传输数据(AES)
- 数字签名防止篡改
- 证书验证防止中间人