资讯动态

XSS挑战靶场19关通关实录:从反射型到DOM型的绕过技巧与防御启示

发布时间:2026/10/18 23:31:05 来源:尧图企业网站定制
1. 从零开始理解XSS挑战靶场的核心设计逻辑1.1 为什么选择靶场模式来学习XSS刚接触Web安全那会儿我试过直接拿真实站点练手结果要么是找不到注入点要么是打进去了也不知道为什么能打进去。后来一位做渗透测试的朋友跟我说了句话我记到现在“你连漏洞怎么形成的都说不清楚就别谈什么利用了。”这句话点醒了我于是我开始系统性地刷各类XSS挑战靶场。XSS挑战靶场最大的价值在于它把真实环境中复杂的业务逻辑剥离掉只留下最核心的漏洞触发链路。每一关都是一个独立的、精心设计的场景让你在最短时间内理解一种特定的XSS防御绕过思路。这就像学武术要先练套路一样靶场就是XSS的“套路训练场”。你不需要考虑WAF、CDN、业务鉴权这些干扰因素只需要专注于一件事怎么让浏览器执行你注入的脚本。这套挑战一共19关难度从最基础的无过滤反射型XSS一路爬升到需要组合多种技巧才能绕过的场景。我前后刷了三遍第一遍是照着Writeup抄第二遍是自己琢磨每一关的过滤逻辑第三遍是尝试用不同的Payload去实现同一个目标。三遍下来对XSS的理解完全不一样了。1.2 靶场环境搭建与基础准备搭建环境这件事我踩过不少坑。最早用的是某集成环境一键部署结果PHP版本和靶场代码不兼容第一关就报错。后来换成手动配置反而顺利很多。推荐的环境组合是PHP 5.6到7.4之间太新的PHP版本某些函数行为有变化MySQL 5.7Web服务器用Apache或者Nginx都行。数据库只需要创建一个简单的库导入靶场自带的SQL文件即可。如果你不想折腾环境用Docker拉一个LAMP镜像是最省事的方案几分钟就能跑起来。浏览器方面我强烈建议用Chrome或者Firefox并且养成按F12打开开发者工具的习惯。Network面板看请求和响应Console面板看脚本执行情况Elements面板看DOM结构变化。这三个面板在后续的挑战中会反复用到。还有一个容易被忽略的准备工作关闭浏览器的XSS Auditor。Chrome早期版本有内置的XSS审计功能会在检测到反射型XSS时自动拦截页面渲染。虽然新版本Chrome已经移除了这个功能但如果你用的是旧版本或者其他基于Chromium的浏览器最好确认一下这个选项的状态。Firefox的话可以在about:config里检查相关设置。注意靶场环境一定要搭在本地或者隔离的虚拟机里不要部署在公网可访问的服务器上。这不是技术问题是基本的安全意识问题。1.3 理解XSS的三种基本类型在正式进入关卡之前有必要把XSS的基本分类理清楚。很多人刷完靶场还是分不清反射型、存储型和DOM型的区别这会导致在实际挖洞时判断失误。反射型XSS是最常见的一种。你提交的恶意脚本作为请求参数发给服务器服务器没做处理就直接“反射”回响应页面里浏览器解析执行。这种XSS不会持久化存储在服务器上每次触发都需要构造一次完整的URL。第1到第10关基本都是这个类型。存储型XSS的危害更大。你的恶意脚本被服务器存进了数据库其他用户访问包含这段数据的页面时就会自动触发。这种XSS不需要诱导用户点击特定链接只要用户正常访问页面就会中招。靶场中后段有几关模拟的就是这种场景。DOM型XSS比较特殊它的漏洞点不在服务器端的响应里而在前端JavaScript代码中。服务器返回的HTML可能是安全的但页面上的JS代码从URL中读取数据并写入DOM时没有做过滤导致脚本执行。这种XSS在查看网页源代码时可能看不到Payload需要审计JS代码才能发现。理解了这三种类型的区别后面的关卡分析就会顺畅很多。每一关我会先判断它属于哪种类型然后再针对性地构造Payload。2. 前六关基础反射型XSS的层层递进2.1 第一关到第三关无过滤到简单过滤第一关是最纯粹的反射型XSS没有任何过滤。你在输入框里输入什么它就原封不动地显示在页面上。这种关卡的意义在于让你熟悉最基本的测试流程输入一个特殊字符观察它是否被转义然后逐步构造完整的Payload。我的习惯是先输入一个尖括号看看它是否被HTML实体编码。如果原样输出说明存在注入可能。然后输入scriptalert(1)/script如果弹窗出现第一关就过了。这一关的Payload就是最经典的scriptalert(1)/script第二关开始加入了一点过滤。你输入的内容会被放入一个input标签的value属性中。这时候直接输入script标签是不行的因为尖括号会被转义。但你可以利用属性闭合的思路先闭合value属性的引号然后插入事件处理函数。具体来说如果页面代码是input value你的输入你可以输入scriptalert(1)/script这样闭合后的HTML就变成了input valuescriptalert(1)/script脚本就能执行了。这一关教会你的是不要只盯着标签注入属性注入同样有效。第三关的过滤规则又变了。它把尖括号和双引号都做了转义但单引号没有处理。这时候你需要换一种思路如果输入点在一个单引号包裹的属性里你可以用单引号闭合然后注入事件处理函数。比如输入 onmouseoveralert(1)当鼠标移到输入框上时就会触发。这三关连起来看其实是在教你一个核心方法论先判断输出上下文再选择对应的绕过策略。输出在HTML标签之间、在属性值里、在JavaScript代码里对应的Payload构造方式完全不同。2.2 第四关到第六关事件处理与编码绕过第四关的输出点又回到了HTML标签之间但过滤规则变成了把尖括号转义。这时候script标签用不了了需要换用其他不需要尖括号的执行方式。我常用的替代方案是利用HTML的事件属性。比如img srcx onerroralert(1)但这里尖括号被过滤了所以需要换一种思路。如果输入点在一个已经存在的标签属性里可以直接注入事件。比如页面代码是input value你的输入你可以输入 onfocusalert(1) autofocus页面加载时自动聚焦到输入框触发onfocus事件。第五关的过滤更严格了script关键字被列入了黑名单。这时候可以用大小写混写来绕过比如ScRiPtalert(1)/ScRiPt。如果大小写也被处理了还可以用HTML实体编码比如#x3c;script#x3e;。不过要注意HTML实体编码在标签内部和属性值里的解析规则是不一样的需要根据具体上下文来调整。第六关开始涉及URL编码的绕过。有些过滤只检查原始输入不检查URL解码后的内容。你可以把Payload做两次URL编码服务器解码一次后得到的是编码过的Payload但浏览器在解析时还会再解码一次最终执行的是原始Payload。这种双重编码的技巧在实际漏洞挖掘中非常常见。实操心得在判断过滤规则时不要只测试一种Payload。我通常会准备一个测试向量列表包括、、、、(、)、script、alert、on等关键字逐个输入观察哪些被转义、哪些被删除、哪些原样输出。这个测试过程比直接猜过滤规则高效得多。3. 中段关卡过滤规则升级与绕过思路3.1 第七关到第十关黑名单与白名单的博弈从第七关开始过滤规则从简单的字符转义升级到了黑名单机制。所谓黑名单就是把已知的危险字符和关键字列出来发现就删除或者替换。这种防御方式的问题在于黑名单永远不可能穷举所有可能的攻击向量。第七关的黑名单里包含了script、on、src等常见关键字。我试过用scrscriptipt这种嵌套写法来绕过因为过滤函数只做一次替换把中间的script删掉后剩下的部分刚好拼成script。这种“删除式过滤”的绕过思路在早期Web应用中非常有效。第八关引入了大小写敏感的问题。如果过滤函数只匹配小写的script那用SCRIPT或者ScRiPt就能绕过。但如果过滤函数用了不区分大小写的匹配这条路就走不通了需要换其他标签比如img、svg、details等。第九关的过滤规则里增加了对空格的处理。有些过滤会把空格替换成下划线或者直接删除。这时候可以用Tab字符、换行符、注释符来替代空格。比如img/srcx/onerroralert(1)用斜杠代替空格来分隔属性。或者用img%09srcx%09onerroralert(1)用Tab的URL编码来分隔。第十关是我个人觉得比较有意思的一关。它把alert关键字也加入了黑名单。这时候可以用confirm、prompt、console.log来替代或者用字符串拼接的方式构造alert比如window[alert](1)。如果连window都被过滤了还可以用top、self、parent这些全局对象来替代。3.2 第十一关到第十三关DOM型XSS的独特挑战第十一关开始进入DOM型XSS的领域。这一关的服务器端响应是完全安全的你输入的内容在HTML源码里找不到。但页面上的JavaScript代码会从URL的hash部分或者查询参数中读取数据然后用innerHTML或者document.write写入页面。这种场景下查看网页源代码是没用的必须打开开发者工具在Sources面板里找到对应的JS文件逐行审计代码。我通常会搜索innerHTML、document.write、eval、setTimeout、location等关键字快速定位可能存在漏洞的代码段。第十二关的DOM型XSS涉及eval函数。页面代码大概是这样的eval(var x location.hash.substring(1) )。这种情况下你需要闭合前面的引号然后注入自己的代码。比如URL的hash部分输入;alert(1);//闭合后的代码就变成了eval(var x ;alert(1);//)脚本执行。第十三关的难点在于过滤了括号和引号。这时候需要用模板字符串或者String.fromCharCode来构造Payload。比如alert可以用top[alert]来替代括号可以用反引号加模板字符串来绕过。这一关让我深刻体会到JavaScript的灵活性既是它的优势也是XSS防御的噩梦。注意DOM型XSS的测试一定要在浏览器的开发者工具里进行因为Payload可能不会出现在页面的HTML源码中。另外不同浏览器对URL编码的解析规则可能有细微差异建议在多个浏览器里都测试一遍。3.3 第十四关到第十六关存储型XSS与持久化攻击第十四关开始模拟存储型XSS的场景。你提交的内容会被保存到数据库然后在另一个页面展示。这种XSS的危害在于任何访问该页面的用户都会触发脚本不需要诱导点击。这一关的过滤规则通常比反射型更严格因为开发者知道存储型XSS的危害更大。但过滤逻辑往往还是黑名单那一套只是黑名单更长了。我试过用svg/onloadalert(1)来绕过因为svg标签不在黑名单里而onload事件在SVG标签中是有效的。第十五关的存储型XSS涉及富文本编辑器。这种场景下用户输入的内容会经过HTML净化处理但净化规则可能存在漏洞。比如某些净化库只处理了script标签但没处理iframe、object、embed等标签。或者净化规则在处理嵌套标签时存在逻辑缺陷可以通过构造特殊的嵌套结构来绕过。第十六关的难点在于输出点的上下文比较复杂。你输入的内容可能被拆分到多个HTML属性中或者被插入到JavaScript代码的字符串里。这时候需要仔细分析输出点的结构构造针对性的Payload。我通常会先用一个简单的测试字符串比如AAA\观察它在页面中的输出位置和转义情况然后再决定用什么Payload。4. 后段关卡组合技巧与高级绕过4.1 第十七关到第十八关编码与协议的综合运用第十七关的过滤规则非常严格几乎所有的HTML标签和事件属性都被列入了黑名单。这时候需要用到一些比较冷门的技巧比如利用a标签的href属性执行JavaScript协议。Payload大概是这样的a hrefjavascript:alert(1)click/a。但如果javascript关键字被过滤了可以用HTML实体编码来绕过比如#106;avascript:alert(1)。或者用data:协议比如a hrefdata:text/html,scriptalert(1)/scriptclick/a。第十八关涉及CSS注入。有些页面允许用户自定义样式但没有对CSS内容做充分过滤。你可以利用CSS的expression()函数仅限旧版IE或者url()函数来执行脚本。虽然现代浏览器已经不支持expression()了但url()配合javascript:协议在某些场景下仍然有效。这一关还涉及到一个重要的概念mXSS突变型XSS。所谓突变型XSS是指浏览器在解析HTML时会对某些不合法的结构进行自动修正修正后的DOM结构与原始HTML不同可能导致原本被过滤的Payload重新生效。比如某些标签的嵌套规则、属性的解析顺序等都可能被利用来绕过过滤。4.2 第十九关终极挑战与思路总结第十九关是整个靶场的收官之战通常需要组合前面学到的多种技巧才能通过。这一关的过滤规则可能包括黑名单关键字、字符转义、长度限制、编码检测等多个层面。我的通关思路是分步骤进行的。第一步先用一个简单的测试向量确定输出点的上下文。第二步根据上下文选择可用的标签和事件。第三步针对过滤规则选择编码方式或替代方案。第四步如果长度有限制尝试用短域名、外部JS文件或者eval压缩代码来缩短Payload。这一关让我意识到XSS防御和XSS攻击本质上是一场成本博弈。防御方要覆盖所有可能的攻击向量而攻击方只需要找到一个遗漏点。这也是为什么XSS漏洞至今仍然是最常见的Web漏洞之一。下面这张表总结了19关的核心考点和绕过思路方便你快速回顾关卡范围核心考点典型绕过思路第1-3关基础反射型XSS、属性注入标签注入、属性闭合、事件处理第4-6关事件处理、编码绕过大小写混写、HTML实体编码、双重URL编码第7-10关黑名单过滤、关键字替换嵌套标签、替代函数、字符串拼接第11-13关DOM型XSS、JS代码审计闭合引号、模板字符串、fromCharCode第14-16关存储型XSS、富文本净化SVG标签、冷门事件、嵌套结构第17-18关协议注入、CSS注入、mXSSjavascript协议、data协议、突变型XSS第19关综合挑战多技巧组合、长度压缩、外部引用5. 常见问题与排查技巧实录5.1 Payload不弹窗的排查思路刷靶场的过程中最让人抓狂的就是Payload明明构造对了但就是不弹窗。我总结了一套排查流程基本上能覆盖90%以上的情况。第一步确认输出点。在开发者工具的Elements面板里搜索你输入的测试字符串看看它出现在HTML的什么位置。是在标签之间、属性值里、还是JavaScript代码里不同的位置对应完全不同的Payload构造方式。第二步检查转义情况。看看你的特殊字符被转义成了什么。变成了lt;变成了quot;还是直接被删除了根据转义规则调整Payload。第三步查看Console报错。如果Payload被浏览器拦截或者解析出错Console面板会有报错信息。比如“Refused to execute inline script”说明触发了CSP策略“Uncaught SyntaxError”说明JavaScript语法有问题。第四步确认事件是否触发。如果你用的是onmouseover、onclick这类事件需要手动触发才能执行。换成onload、onerror、autofocus这类自动触发的事件试试。第五步检查浏览器版本。有些Payload在旧版浏览器里有效在新版浏览器里已经被修复了。比如script标签在innerHTML中插入时不会执行这是现代浏览器的安全机制。5.2 过滤规则判断的实用技巧很多新手在刷靶场时喜欢直接看Writeup抄Payload但不知道为什么要用这个Payload。我的建议是每关先自己测试过滤规则把测试结果记录下来形成自己的“过滤规则字典”。具体做法是准备一组测试字符包括、、、、(、)、/、\、;、:、、空格、Tab、换行以及script、alert、on、src、href、eval等关键字。逐个输入观察每个字符或关键字在输出中的变化。是原样输出、被转义、被删除、还是被替换成其他字符这个测试过程大概需要五到十分钟但能让你对过滤规则有一个精确的认知后续构造Payload时就不用反复试错了。而且这个习惯在实际漏洞挖掘中同样适用面对一个陌生的目标站点先用测试向量摸清过滤规则再针对性地构造Payload效率会高很多。5.3 从靶场到实战的思维转变靶场通关了不代表实战就能挖到XSS。靶场的输出点是明确的过滤规则是固定的但真实环境要复杂得多。我在实战中踩过的坑包括输出点被JavaScript动态修改、过滤规则在前后端不一致、CSP策略限制了脚本执行、HttpOnly标志导致Cookie无法读取等。从靶场到实战需要补充的知识包括CSP策略的绕过技巧、HttpOnly和Secure标志的影响、前端框架如React、Vue的XSS防御机制、WAF的绕过思路等。这些内容在靶场里涉及得比较少但在实战中非常关键。另外实战中还要考虑XSS的利用方式。弹窗只是证明漏洞存在真正的利用可能包括窃取Cookie、发起CSRF攻击、进行钓鱼、传播蠕虫等。不同的利用方式对Payload的要求不同比如窃取Cookie需要document.cookie可读发起CSRF需要构造特定的请求。实操心得我习惯在本地维护一个XSS Payload库按照输出上下文、过滤规则、浏览器类型等维度分类整理。每次遇到新的场景先从库里找相似的案例再根据实际情况调整。这个习惯让我在实战中节省了大量时间。6. 工具选型与效率提升方案6.1 浏览器开发者工具的深度使用很多人只用开发者工具看个Console其实它的功能远不止于此。在XSS测试中我常用的功能包括Elements面板的实时编辑你可以直接在Elements面板里修改HTML结构测试不同的Payload效果不用反复提交表单。这对于理解输出上下文特别有帮助。Network面板的请求重放找到提交Payload的请求右键选择“Edit and Resend”可以直接修改请求参数重新发送不用回到页面上重新输入。这在测试不同Payload时非常高效。Sources面板的断点调试对于DOM型XSS可以在关键的JavaScript代码行设置断点单步执行观察变量的变化。这比盲猜过滤规则要准确得多。Console面板的API调用你可以直接在Console里调用页面上的JavaScript函数测试它们的行为。比如document.write(scriptalert(1)/script)看看是否会执行。6.2 辅助工具与自动化方案除了浏览器自带的开发者工具还有一些辅助工具可以提升效率。Burp Suite是Web安全测试的标配工具。它的Proxy模块可以拦截和修改请求Repeater模块可以重放请求Intruder模块可以批量测试Payload。在刷靶场时我通常用Burp的Proxy拦截提交请求然后在Repeater里反复修改Payload测试。XSStrike是一个专门针对XSS的自动化测试工具。它可以自动分析输出上下文生成针对性的Payload并检测过滤规则。不过我不建议新手一开始就用自动化工具因为你会错过理解漏洞原理的机会。等手动刷完一遍靶场之后再用自动化工具验证自己的思路效果更好。PayloadsAllTheThings是一个开源的Payload集合包含了各种场景下的XSS Payload。我通常把它作为参考手册遇到卡壳的关卡时翻一翻看看有没有类似的案例。6.3 个人知识管理方案刷完19关之后如果不做整理过一段时间就会忘得差不多了。我的做法是每关写一篇简短的笔记记录以下内容关卡编号、输出上下文、过滤规则、最终Payload、绕过思路、踩过的坑。这些笔记我放在一个本地的Markdown文件里按照关卡顺序排列。每隔一段时间回顾一遍或者遇到类似的实战场景时翻出来参考。这个习惯让我在后续的漏洞挖掘中能够快速回忆起相关的绕过技巧。另外我还维护了一个“Payload速查表”按照输出上下文分类HTML标签之间、属性值里、JavaScript代码里、CSS样式里、URL参数里。每个分类下列出常用的Payload和对应的触发条件。这个速查表在实战中非常实用基本上覆盖了80%以上的常见场景。7. 影响范围分析与防御启示7.1 XSS漏洞的实际影响范围XSS漏洞的影响范围取决于多个因素漏洞的类型反射型、存储型、DOM型、触发的位置首页、后台、用户中心、访问量的大小、以及漏洞的利用方式。反射型XSS需要诱导用户点击特制链接才能触发影响范围相对有限但如果结合钓鱼手段仍然可以造成可观的危害。存储型XSS的影响范围最大任何访问受影响页面的用户都会中招如果漏洞出现在高访问量的页面如论坛帖子、商品评论可能在短时间内影响大量用户。DOM型XSS的影响范围取决于漏洞代码的执行位置如果是在登录页面或者支付页面危害同样很大。从利用方式来看XSS可以导致用户Cookie被窃取、会话被劫持、页面内容被篡改、恶意脚本被注入、用户被重定向到钓鱼页面、敏感信息被窃取等。如果受影响用户具有管理员权限攻击者可能进一步控制整个后台系统。7.2 从攻击视角看防御策略刷完这19关我对XSS防御也有了更深的理解。有效的防御策略应该是多层次的输入验证是第一道防线。对所有用户输入进行严格的类型、长度、格式验证拒绝不符合预期的输入。但输入验证不能作为唯一防线因为有些场景下用户需要输入特殊字符如富文本编辑器。输出编码是最核心的防御手段。根据输出上下文HTML、属性、JavaScript、CSS、URL选择对应的编码方式。HTML实体编码、JavaScript编码、URL编码各有适用场景不能混用。内容安全策略CSP是最后一道防线。通过设置CSP头限制页面可以加载和执行的脚本来源即使攻击者成功注入了脚本也无法执行。CSP的配置需要根据业务需求仔细调整过于宽松的CSP形同虚设过于严格的CSP可能影响正常功能。HttpOnly标志可以防止JavaScript读取Cookie降低Cookie被窃取的风险。但HttpOnly不能阻止XSS的其他利用方式如发起CSRF攻击或篡改页面内容。注意没有任何单一防御措施能够完全杜绝XSS。防御方需要假设每一层防线都可能被绕过通过多层防御来增加攻击者的成本。7.3 持续学习与能力提升路径XSS只是Web安全的一个切入点。刷完这个靶场之后可以继续深入的方向包括CSRF、SSRF、SQL注入、文件上传漏洞、反序列化漏洞等。每个方向都有对应的靶场和练习平台。我的学习路径是先刷靶场理解漏洞原理然后在本地搭建漏洞环境进行实战练习最后在授权的测试环境中验证自己的技能。这个过程需要持续积累不可能一蹴而就。另外关注安全社区的最新动态也很重要。新的绕过技巧和防御方案不断涌现保持学习才能跟上节奏。我通常会关注几个高质量的安全博客和漏洞披露平台了解最新的漏洞案例和利用技巧。最后再分享一个小技巧在刷靶场时不要满足于“弹窗成功”这个结果。尝试用不同的Payload实现同一个目标理解每种Payload的适用场景和局限性。这种刻意练习会让你对XSS的理解从“知道怎么打”提升到“知道为什么能打”的层次。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑