web学习笔记编程技术学习与分享

XSS 的三种类型与防御

2026 年 08 月 24 日约 3 分钟阅读 网络与安全

XSS 的本质是:攻击者的输入被浏览器当成了代码。按注入路径分三类,防御思路是相通的。

三种类型

存储型:恶意脚本存进数据库(如评论),每个访问者都会执行。危害最大,影响面最广。

反射型:脚本在 URL 参数里,服务端原样输出到页面。需要诱导用户点特定链接,常见于搜索结果页。

DOM 型:纯前端问题,服务端完全无辜:

// 反例:location.hash 直接进 innerHTML
document.getElementById('tip').innerHTML = '欢迎 ' + location.hash.slice(1);

防御的层次

第一层(最有效):输出编码。 数据回显到什么上下文,就用什么编码——这是 XSS 防御的核心原则:

  • HTML 正文:< > & " ' 实体化;
  • 属性值:加引号 + HTML 编码;
  • <script> 内 / JSON:防 </script> 逃逸,用 JSON 库的转义而非手拼;
  • URL:encodeURIComponent,而不是 encodeURI。

第二层:CSP。 内容安全策略限制脚本来源,即使注入成功也难执行:

Content-Security-Policy: default-src 'self'; script-src 'self' cdn.example.com; object-src 'none'

注意 unsafe-inline 会大幅削弱 CSP,能不用就不用。CSP 是兜底不是替代,输出编码依然是第一优先。

第三层:框架默认安全。 React/Vue 默认对插值转义。危险操作集中在 dangerouslySetInnerHTML、v-html,评审时重点看这几处,并明确「为什么这里必须富文本」。

富文本怎么办

需要用户发 HTML(评论、文章)时,用白名单净化库(服务端 HTMLPurifier,前端 DOMPurify),绝不用正则过滤——绕过手段(属性拆分、大小写、编码嵌套)远超正则的表达能力。同时封禁 javascript: 伪协议、on* 事件属性、<iframe>。

setcookie('sid', $v, ['httponly' => true, 'secure' => true, 'samesite' => 'Lax']);

HttpOnly 让脚本读不到会话 Cookie,XSS 偷不走登录态。它不解决 XSS,但把损失从「接管账号」降到「污染页面」。

自测方法:在所有输入点提交 '"()<script>alert(1)</script>,逐个输出位置检查是否被编码。这个土办法比扫描器先发现问题。

XSS安全前端