xss-labs-masters第8关
先把场景捋清楚XSS-Labs Level81、关卡防御清单为什么老 payload 全部失效后端做了多层过滤htmlspecialchars实体化同时转义 小写转换关键词替换过滤src、data、onfocus、href、script不能用事件onxxx、不能新建标签、不能直接写javascript:可控输出位置html预览a href【我们输入的内容】友情链接/a重点输入会直接放进a的href 属性值里面。2、核心问题为什么必须用 HTML 十进制实体#数字;① 后端过滤是【原始字符串匹配】如果你直接提交明文plaintextjavascript:alert()后端拿到原始请求参数一眼识别出javascript直接拦截 / 替换。但你提交plaintext#106;#97;#118;#97;#115;#99;#114;#105;#112;#116;#58;#97;#108;#101;#114;#116;#40;#41;后端看到的只是一串#数字;不存在连续字母javascript过滤器匹配不到关键词 →成功绕过后端黑名单。② 浏览器解析规则最关键浏览器渲染页面时分两步HTML 解析阶段对标签属性内的HTML 实体自动解码#106;→j整串实体全部还原成明文javascript:alert()解码完成后再交给 URL 解析器处理 href 浏览器识别出javascript: 伪协议点击链接 → 执行 JS 代码一句话精髓后端看编码后的字符串识别不出关键词浏览器渲染时自动解码拿到真实恶意代码。3、和上一关onfocus 单引号闭合本质区别上一关思路 利用漏转单引号→ 冲出属性边界追加onfocus事件 本关为什么这条路行不通过滤所有onxxx关键词双引号被htmlspecialchars实体化很难闭合属性不能新建任何标签虽然被实体化就算不用on 系列也被黑名单拦截只剩下唯一可行入口利用 a 标签 href javascript 伪协议 HTML 实体编码绕过黑名单4、回答你最关心htmlspecialchars 在这里起了什么作用会不会破坏 payloadhtmlspecialchars只会转义 我们 payload 里面大量#xxx;会被转义成amp;❌ ⚠️重点源码细节XSSlabs level8 关键后端逻辑顺序先执行关键词过滤 → 再执行 htmlspecialchars不是先转义再过滤 所以 我们输入#106;...过滤阶段没有 javascript放行再送入 htmlspecialchars 此时字符串内的会被转义为amp; 不对原靶场源码php运行$str2strtolower($str); $str3str_replace(on,o_n,$str2); $str4str_replace(src,sr_c,$str3); $str5str_replace(data,da_ta,$str4); $str6str_replace(href,hr_ef,$str5); $str7str_replace(,quot;,$str6); echo a href.$str7.友情链接/a;它没有用完整 htmlspecialchars只是手动替换双引号这就是漏洞根源 不会把转成amp;实体#xxx;完整保留下发到前端。 浏览器正常解码攻击成立。延伸思考 如果后端【先 htmlspecialchars 转义 变成 再过滤】这个 payload 直接报废#106;→amp;#106;浏览器再也无法解码出字母 j。5、整条攻击链路完整演示Payload#106;#97;#118;#97;#115;#99;#114;#105;#112;#116;#58;#97;#108;#101;#114;#116;#40;#41;浏览器提交 payload 到 PHPPHP 小写转换 黑名单关键词扫描找不到 javascript、on、script放行PHP 只简单转义双引号不处理 符号直接拼进 HTML 输出页面源码html预览a href#106;#97;#118;#97;#115;#99;#114;#105;#112;#116;#58;#97;#108;#101;#114;#116;#40;#41;友情链接/a用户打开页面浏览器解析 HTML href 内部实体解码 →javascript:alert()用户点击友情链接触发伪协议执行弹窗总结为什么只能选用这个方案事件类 payload (onfocus/onclick)关键词被黑名单过滤直接失效直接明文javascript:后端字符串匹配拦截无法闭合标签 / 属性注入新 HTML防御强化✅ HTML 十进制实体后端看不到明文关键词、浏览器自动解码、href 支持 javascript 伪协议完美契合当前场景拓展考点面试常问href 支持 HTML 十进制实体、十六进制实体#x6a;on 事件里面同样支持 HTML 实体解码但这一关 on 被过滤所以不能用URL 编码不能在这里直接使用href 不会自动 URL 解码只有 HTML 实体能被自动解码防御方案禁止 href 使用 javascript: 伪协议白名单 http/https不要简单黑名单过滤黑名单永远能编码绕过严格输出编码 上下文感知过滤如果你需要我把十进制实体、十六进制实体两种 payload 都写给你对比。unicode 编码和 html 编码是同一种嘛一句话结论不是同一种东西完全两个体系只是长得有点像经常被混淆。先分清名词Unicode一套全球字符编号标准字符→数字码点HTML 实体编码HTML 编码HTML 语法里的转义写法可以基于 Unicode 码点来写1. 基础概念拆解Unicode所有字符分配唯一数字码点j的 Unicode 码点U006A十进制 106 它只是字符编号规则本身不是传输 / 网页编码格式。HTML 实体编码HTML 编码是浏览器 HTML 解析器识别的语法两种格式十进制实体#十进制数字;j→#106;十六进制实体#x十六进制数字;j→#x6a;✔ 关键关系 HTML 实体里写的数字用的就是 Unicode 码点数值所以 HTML 实体依托 Unicode但 ≠ Unicode 编码。2. 通俗类比Unicode 每个人的身份证号HTML 实体 “用身份证号找人” 的书面格式#号码;身份证号 ≠ 那张纸条这就是二者区别。3. 极易踩坑区分渗透测试必考① HTML 实体编码#106;/#x6a;生效场景HTML 解析阶段a href#106;#97;#118;#97;...浏览器读 HTML 的时候自动解码在 JS 字符串内部、URL 里不会自动解码② URL 编码百分编码%xx和两者又完全无关j→%6A浏览器解析 URL 时解码HTML 阶段不解码。③ UTF-8是 Unicode 的二进制存储方案和网页绕过基本不直接打交道。4. 回到你 Level8 的 payload 重点解释Payload#106;#97;#118;...很多人口头叫它 “Unicode 编码”这是不严谨的俗称标准叫法HTML 十进制数字实体为什么大家会混淆 因为实体内部数字来源是 Unicode 码点久而久之圈内随口叫成 Unicode 编码。5. 关键边界XSS 绕过必记HTML 解析器只会自动解 HTML 实体#xxx;HTML 解析器不会自动解 URL 编码%xxHTML 解析器不会自动解 JS 内部的 \uXXXX Unicode 转义举例子对比三者写法字符 jUnicode 码点U006AHTML 十进制实体#106;HTML 十六进制实体#x6a;JS 字符串 Unicode 转义\u006aURL 编码%6A6. 经典误区澄清误区#106;就是 Unicode 编码 ✅ 纠正#106;是HTML 语法属于 HTML 实体 里面数字的值取自 Unicode载体、解析时机完全不同。7. 延伸考点对应你这套 XSS 靶场a href属性内支持 HTML 实体解码level8 能用onclickxxx事件内部先 HTML 解码再 JS 引擎解析双层解析如果放在 JS 脚本script标签里HTML 实体不会自动解码这时候要用\uXXXX如果你想要我整理一张表格把 HTML 实体 / JS Unicode 转义 / URL 编码 三者适用场景汇总方便区分什么时候哪种编码能用、哪种无效。这里只要 JavaScriptalertI就行为什么不要 οnfοcus核心答案分两层讲清楚1、先看输出位置决定能用什么 payload源码输出点echo centerBRa href.$str7.友情链接/a/center;你的输入最终放在a标签href这里两种思路对比思路 Aοnfοcusxxx上一关打法想要实现效果payload 需要 onfocusalert() autofocus 作用闭合原有双引号新增 onfocus 事件属性❌ 在 Level8 里面这套直接废掉两个致命原因后端黑名单过滤on源码存在替换逻辑$str3str_replace(on,o_n,$str2);只要出现连续字符on直接被篡改。onfocus→o_nfocus事件彻底失效。虽然你可以尝试编码绕过 on 过滤但这条路没必要关卡提供了更天然的入口。思路 Bjavascript:alert ()本关标准答案不需要新增任何事件a hrefjavascript:alert()href 本身原生支持 javascript 伪协议浏览器规则点击 a 标签读取 href 的值如果是javascript:开头直接执行后面 JS 代码。 ✅完全不需要 onxxx 系列事件避开了 on 关键词黑名单2、博主文案的误区纠正重点原文说利用 href 的隐藏属性自动 Unicode 解码 不严谨标准说法 不是 href 独有的特性所有 HTML 标签属性内浏览器 HTML 解析阶段都会自动解码 HTML 实体#106;这类。真正完整攻击逻辑明文javascript:alert()含有字符串javascript后端黑名单匹配拦截把文字转为HTML 十进制实体#106;#97;...后端收到 payload看到的只有#数字;不存在连续字母 javascript过滤器放行PHP 只手动转义双引号不处理 符号实体完整输出到页面浏览器解析 HTML自动把#xxx;解码还原成javascript:alert()点击链接href 伪协议执行 JS 弹窗。3、一句话总结区别onfocus给现有标签新增事件依赖on关键词本关卡直接被过滤走不通javascript:伪协议直接利用 href 原生执行能力不需要任何 on 事件完美绕开 on 黑名单。4、延伸考点面试 / 刷题常问哪些标签支持javascript:伪协议a href、area href、iframe src等如果输出位置不在 href/src而是普通文本伪协议无效只能考虑事件注入区分两个场景属性内可用伪协议 → 优先伪协议规避 on 过滤无 href/src 输出点 → 只能尝试事件注入onclick/onmouseover 等补充为什么上一关能用 onfocus上一关输出位置是input value输入内容没有黑名单拦截 on并且单引号没有转义可以闭合属性追加事件 Level8 增加了on关键词过滤这条路直接封死只能切换思路使用 href 伪协议。