XSS攻击与防御详解
字数 1476 2025-11-05 23:47:39
XSS攻击与防御详解
一、XSS攻击描述
XSS(跨站脚本攻击)是一种客户端安全漏洞,攻击者将恶意脚本注入到可信网站中,当用户访问被注入的网页时,恶意脚本会在用户浏览器执行,从而盗取Cookie、会话令牌等敏感信息,或进行其他恶意操作。
XSS攻击本质是"浏览器将用户输入误当作代码执行",主要分为三类:
- 反射型XSS:恶意脚本作为请求的一部分发送到服务器,服务器直接返回包含恶意脚本的响应
- 存储型XSS:恶意脚本被永久存储在服务器端(如数据库),每次用户访问相关页面都会执行
- DOM型XSS:完全在客户端发生的攻击,恶意脚本通过修改DOM树来实施
二、XSS攻击原理深入分析
-
反射型XSS攻击过程:
- 攻击者构造包含恶意脚本的URL:
http://example.com/search?q=<script>alert('XSS')</script> - 诱使用户点击该链接(通过邮件、社交工程等方式)
- 服务器收到请求后,未经验证直接将搜索参数返回给浏览器
- 浏览器执行响应中的恶意脚本
- 攻击者构造包含恶意脚本的URL:
-
存储型XSS攻击过程:
- 攻击者在论坛、评论区等可存储内容的地方提交恶意脚本
- 恶意脚本被保存到服务器数据库
- 其他用户访问包含该内容的页面时,恶意脚本自动执行
- 危害更大,因为会影响所有访问该页面的用户
-
DOM型XSS攻击过程:
- 恶意脚本通过修改页面DOM结构来实施攻击
- 示例:
http://example.com#<script>alert('XSS')</script> - 客户端JavaScript直接使用location.hash等未经验证的数据操作DOM
- 不经过服务器,完全在客户端完成攻击
三、XSS攻击危害具体表现
- Cookie窃取:通过
document.cookie获取用户会话标识 - 会话劫持:利用窃取的Cookie冒充用户身份
- 钓鱼攻击:伪造登录表单诱导用户输入凭证
- 键盘记录:监听用户的键盘输入
- 网络蠕虫:自动传播的XSS攻击
- Defacement:篡改网页内容
四、XSS防御措施详解
4.1 输入验证与过滤
- 白名单过滤:只允许特定的安全字符通过
- HTML实体编码:将特殊字符转换为HTML实体
< 转换为 < > 转换为 > " 转换为 " ' 转换为 ' & 转换为 & - 上下文相关的编码:
- HTML正文:对
< > & ' "进行编码 - HTML属性:对除字母数字外的所有字符编码
- JavaScript:使用
\xHH格式编码 - URL参数:进行URL编码
- HTML正文:对
4.2 输出编码
- 在数据展示到页面之前进行编码处理
- 根据输出位置采用不同的编码策略:
// HTML内容编码 function encodeHTML(str) { return str.replace(/[&<>"']/g, function(match) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[match]; }); }
4.3 内容安全策略(CSP)
- 通过HTTP头定义可信的内容来源
- 示例CSP策略:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; object-src 'none' - 关键指令:
default-src:默认加载策略script-src:控制JavaScript加载来源style-src:控制CSS加载来源img-src:控制图片加载来源
4.4 HttpOnly Cookie
- 设置Cookie为HttpOnly,防止JavaScript访问
Set-Cookie: sessionid=abc123; HttpOnly; Secure
4.5 其他防御措施
- 输入长度限制:减少攻击载荷空间
- 框架安全功能:使用现代框架(React、Vue等)的内置XSS防护
- 安全编码实践:避免使用
innerHTML、eval()等危险方法 - 正则表达式验证:对特定格式的数据进行严格验证
五、实际防御示例
5.1 安全的评论系统实现
// 后端处理(Node.js示例)
app.post('/comment', (req, res) => {
const content = req.body.content;
// 1. 输入验证
if (!isValidContent(content)) {
return res.status(400).send('Invalid content');
}
// 2. 编码存储(根据需要)
const encodedContent = encodeHTML(content);
// 3. 安全存储到数据库
saveComment(encodedContent);
});
// 前端展示
function displayComment(comment) {
// 使用textContent而不是innerHTML
commentElement.textContent = comment;
// 如果需要富文本,使用安全的HTML净化库
// 如DOMPurify.sanitize(comment)
}
5.2 完整的防御策略组合
// 服务器配置示例
app.use((req, res, next) => {
// 设置CSP头
res.setHeader('Content-Security-Policy',
"default-src 'self'; script-src 'self' 'unsafe-inline'");
// 设置其他安全头
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
next();
});
// Cookie安全设置
app.use(session({
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict'
}
}));
通过这种分层防御策略,可以显著降低XSS攻击的风险。重要的是要理解,XSS防御需要前后端配合,从输入验证到输出编码,再到浏览器安全策略的全面防护。