XSS 攻击是什么?
一、XSS 攻击是什么?
XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的 Web 安全漏洞,攻击者通过在网页中注入恶意脚本(JavaScript、HTML、CSS 等),当用户访问被注入的页面时,恶意脚本会在用户的浏览器中执行,从而实现窃取用户信息(Cookie、Token)、伪造用户操作、劫持会话、植入恶意广告等恶意行为。
XSS 攻击的核心本质:
违背 “前端渲染数据不可执行” 的原则—— 正常情况下,前端展示的用户输入 / 第三方数据应作为 “纯文本” 处理,若被当作 “可执行代码” 解析,就会触发 XSS。
XSS 的分类(按触发方式):
| 类型 | 触发场景 | 示例 |
|---|---|---|
| 存储型 XSS | 恶意脚本被永久存储在服务器(数据库 / 文件),用户访问页面时从服务器加载执行 | 攻击者在论坛发帖时注入 <script>偷Cookie()</script>,所有查看该帖的用户都会执行脚本 |
| 反射型 XSS | 恶意脚本通过 URL 传入,服务器 “反射” 回页面中执行(一次性,不存储) | 攻击者构造链接 http://xxx.com/search?key=<script>恶意代码</script>,用户点击后执行 |
| DOM 型 XSS | 恶意脚本通过前端 DOM 操作直接执行(无需服务器参与) | 前端通过 document.write(location.hash) 将 URL Hash 内容写入页面,若 Hash 含恶意脚本则执行 |
二、XSS 攻击的危害
- 窃取敏感信息:获取用户 Cookie、LocalStorage、Token,冒充用户身份登录系统;
- 劫持用户会话:利用窃取的信息操作用户账户(转账、发帖、修改密码);
- 植入恶意内容:弹出广告、跳转钓鱼网站、挖矿脚本;
- 破坏页面结构:篡改网页内容,诱导用户操作(如虚假登录框)。
三、XSS 攻击的防范方案(核心:输入过滤 + 输出转义 + 安全策略)
1. 核心原则:永远不信任用户输入
所有来自用户、第三方接口、URL 参数的数据,都必须视为 “不可信”,需经过处理后再使用。
2. 输出转义(最基础、最关键)
将渲染到页面中的特殊字符(如 < > & " ')转义为 HTML 实体,让浏览器将其视为纯文本而非可执行代码。
| 特殊字符 | 转义后的 HTML 实体 | 作用 |
|---|---|---|
< |
< |
禁止解析为标签开始 |
> |
> |
禁止解析为标签结束 |
" |
" |
禁止解析为属性引号 |
' |
' |
禁止解析为单引号 |
& |
& |
禁止解析为实体开始 |
实战实现:
原生 JS
:使用
1
textContent
(而非
1
innerHTML
)渲染文本(自动转义);
1
2
3
4// 安全:textContent 会将内容作为纯文本
document.getElementById("content").textContent = userInput;
// 危险:innerHTML 会解析 HTML/脚本
document.getElementById("content").innerHTML = userInput;框架自动转义
:Vue/React 等现代框架默认对插值表达式(
1
{{ }}
/JSX)进行转义,无需手动处理;
1
2
3
4<!-- Vue 安全:自动转义 -->
<div>{{ userInput }}</div>
<!-- Vue 危险:v-html 会解析 HTML,需谨慎使用 -->
<div v-html="userInput"></div>手动转义函数
(针对必须用
1
innerHTML
的场景):
1
2
3
4
5
6
7
8
9
10
11function escapeHtml(str) {
if (!str) return "";
return str
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
// 使用
document.getElementById("content").innerHTML = escapeHtml(userInput);
3. 输入过滤(补充手段)
对用户输入的内容进行 “白名单过滤”—— 只允许合法的字符 / 标签 / 属性,过滤掉恶意内容(如 <script>、onclick 等)。
适用场景:
用户需要输入富文本(如编辑器、评论)时,无法完全转义(需保留部分 HTML 标签),此时需过滤危险标签 / 属性。
实战工具:
专业富文本过滤库:
1
DOMPurify
(主流推荐,能安全过滤恶意代码,保留合法 HTML);
1
2
3
4import DOMPurify from 'dompurify';
// 过滤后再渲染富文本
const safeHtml = DOMPurify.sanitize(userInput);
document.getElementById("editor").innerHTML = safeHtml;后端过滤:如 Java 的
Jsoup、PHP 的HTMLPurifier,对提交的内容进行服务端过滤。
4. 安全策略:CSP(内容安全策略)
CSP 是浏览器的安全机制,通过 HTTP 响应头或 meta 标签限制页面可加载的资源、可执行的脚本来源,从根源上阻止恶意脚本执行(即使漏过了转义 / 过滤)。
核心作用:
- 禁止内联脚本(
<script>...</script>、onclick等); - 禁止未授权的外部脚本(只允许加载指定域名的脚本);
- 禁止
eval()、new Function()等动态执行代码的方式。
实战配置:
HTTP 响应头
(推荐,由服务端设置):
1
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self'; img-src 'self' data:;
解释:
default-src 'self':默认只允许加载同域名资源;script-src 'self' https://cdn.jsdelivr.net:只允许执行同域名和 jsdelivr 的脚本;- 禁止内联脚本、eval 等。
meta 标签
(前端配置,优先级低于响应头):
1
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
5. 其他辅助防范手段
(1)Cookie 保护:HttpOnly + Secure
HttpOnly:设置该属性的 Cookie 无法被 JavaScript 读取(直接阻断窃取 Cookie 的 XSS 攻击);Secure:Cookie 仅在 HTTPS 协议下传输,防止明文传输被劫持;SameSite1
2
3
4
5
6
:限制 Cookie 跨站发送,防止 CSRF 同时辅助防范 XSS。
```http
// 服务端设置 Cookie 响应头
Set-Cookie: sessionId=xxx; HttpOnly; Secure; SameSite=Strict;
(2)避免使用危险的 API
禁用 / 谨慎使用可执行动态代码的 API,减少 XSS 触发点:
- 危险 API:
eval()、new Function()、innerHTML、document.write()、location.hash直接渲染; - 安全替代:
textContent、setAttribute(设置属性)、DOMPurify过滤后再用innerHTML。
(3)服务端验证 + 前端验证双保险
- 前端:做基础的输入格式验证(如手机号、邮箱格式),提升用户体验;
- 服务端:必须重新验证所有输入(前端验证可被绕过),过滤恶意内容。
(4)URL 参数处理
对 URL 中的 query、hash 等参数,转义后再渲染到页面,避免反射型 / DOM 型 XSS:
1 | // 危险:直接将 hash 写入页面 |
四、XSS 防范总结(优先级排序)
- 输出转义:所有非富文本内容用
textContent/ 框架插值渲染,富文本用DOMPurify过滤; - CSP 策略:配置严格的内容安全策略,兜底阻止恶意脚本执行;
- Cookie 保护:设置
HttpOnly/Secure,防止敏感 Cookie 被窃取; - 输入过滤:服务端 + 前端双端过滤危险内容;
- 禁用危险 API:减少不必要的动态代码执行。
五、常见误区
- “前端转义就够了”:前端转义可被绕过(如攻击者直接请求接口),必须在服务端再次转义 / 过滤;
- “富文本无法防范 XSS”:使用
DOMPurify等专业库可安全处理富文本; - “HTTPS 能防 XSS”:HTTPS 仅保证传输安全,无法阻止页面内的恶意脚本执行;
- “框架完全安全”:Vue/React 的
v-html/dangerouslySetInnerHTML仍可能触发 XSS,需谨慎使用。
XSS 攻击的核心是 “脚本注入”,防范的核心是 “让恶意脚本无法执行”—— 通过转义让脚本变成文本,通过 CSP 限制脚本来源,通过 HttpOnly 保护敏感数据,多维度防护才能彻底规避风险。



