PortSwigger靶场之将 XSS 存储到onclick带有尖括号和双引号 HTML 编码以及单引号和反斜杠转义的事件中通关秘籍

一、实验室挑战分析

  • 漏洞类型: 存储型 XSS(在评论功能中)。

  • 目标: 提交评论,使得点击评论作者姓名时触发 alert() 函数。

  • 注入点: 评论作者的姓名网站 输入,被反射到 onclick 事件处理程序中。

  • 防御机制(需要绕过):

    1. 尖括号 (<, >) HTML 编码:尖括号 <> 被 HTML 编码为 &lt;&gt, 阻止注入新的 HTML 标签。无法使用 <script><img><svg> 等标签执行 JS,

      ❌ 无法使用 onloadonerror 等事件处理器(除非通过其他方式)

    2. 双引号 (") HTML 编码:双引号 " 被 HTML 编码为 &quot, 阻止通过闭合属性值来注入新属性或修改现有属性如 onfocusonclick),

      ❌ 无法添加 onmouseover=onload= 等属性

    3. 单引号 (') 转义: 单引号 ' 被转义为 \' , 防止在 JavaScript 字符串中闭合字符串

    4. 反斜杠 (\) 转义: 反斜杠 \ 被转义为 \\ |,防止利用反斜杠"逃逸"转义机制。

  • 利用机制:如果输入被插入到 HTML 属性中(如 onclick),浏览器会先解码 ' 为 ',从而绕过服务端对 ' 的转义;也可以利用表达式执行函数,即使字符串被闭合保护。

    在 HTML 中,' 是表示单引号 ' 的字符实体。浏览器在解析 HTML 标签的属性或文本内容时,会自动将 ' 解码为实际的单引号字符 '

    然而,在 JavaScript 字符串中,' 仅被视为普通字符串序列,不会被自动转换为单引号。

    服务器在接收用户输入时,通常不会自动解码 HTML 实体,也就是说,如果输入中包含 ',服务器默认将其作为字面字符串处理,而非 '。但某些后端框架或应用程序可能会显式调用 HTML 实体解码函数,将 ' 转换为 ' 后再进行后续处理(如转义),这种情况下就可能影响安全过滤逻辑。

    因此,能否利用 ' 来绕过对单引号的转义,关键在于服务器端是否执行了 HTML 实体解码。

二、理论分析

我们进入上面评论页面,输入任意评论和信息并提交,之后查看页面代码如下:

html 复制代码
<a id="author" href="https:/1" onclick="var tracker={track(){}};tracker.track('https:/1');">1</a>
  • <a> 标签是一个超链接,显示作者名1。

  • href="https:/1":显示我们评论填写的 URL

  • onclick="...":当用户点击这个链接时,会执行 JavaScript 代码。

  • 脚本内容:

    javascript 复制代码
    var tracker = { track() {} }; 
    tracker.track('https:/1');
    • 它定义了一个对象 tracker,包含一个空的 track() 方法。
    • 然后调用 tracker.track(...),但由于方法为空,实际什么也不做。

分析完关键语句的脚本内容,我们继续分析。

我们输入的 "Website" 被同时写入了 HTML 标签的 href 属性和 onclick 事件中,具体出现在 tracker.track('http://1') 这一函数调用里。由于该 track 方法体为空,因此即使被调用也不会产生实际影响。

此时,我们可以利用 HTML 实体编码的特性,使用 ' 来绕过对单引号的转义限制。因为 onclick 是 HTML 标签的属性,浏览器在解析该属性值时,会优先将其中的 HTML 实体(如 ')解码为对应的字符 (即 '),然后再将解码后的结果传递给 JavaScript 引擎执行。这意味着,' 会在 JavaScript 执行前被转换为单引号,从而实现字符串的提前闭合。

然而,在提交评论时,系统对 "Website" 字段有格式校验(如必须为合法 URL),因此无法直接输入 JavaScript 函数或恶意脚本。为了绕过这一限制,我们需要将 payload 封装在数学表达式或合法 URL 形式中,其中的 HTML 实体(包括 ')进行解码 ,然后再将解码后的结果传递给 JavaScript 引擎执行。这意味着,即使服务器未解码,只要 ' 出现在 HTML 属性中,浏览器就会将其转换为 ',从而绕过基于字符过滤的防御机制。

三、解决靶场

javascript 复制代码
Payload:http://'-alert(1)-'

在提交评论时候提交网站输入上面payload,对应js会解析为:

javascript 复制代码
'http://' - alert() - ''

当 JavaScript 遇到非数字类型的值参与算术运算(如减法),会尝试将其隐式转换为数字,这里的 'http://' → 不是一个合法的数字格式 → 转换结果为 NaN(Not-a-Number);同时alert() 函数没有返回值 ,在 JavaScript 中,没有返回值的函数默认返回 undefined

接着,JavaScript 开始从左到右计算减法(减法是左结合):

  1. 'http://' - undefined

    → 两者都转为数字:

    • 'http://'NaN
    • undefinedNaN
      NaN - NaN = NaN
  2. 然后计算:NaN - ''

    • ''(空字符串)→ 转为数字是 0
      NaN - 0 = NaN

虽然表达式结果是 NaN,但关键在于:**alert() 已经执行了!**这里我们巧妙的利用数学运算"包装"恶意函数调用。最后成功通关

相关推荐
jerryinwuhan21 小时前
理论及算法_时间抽取论文
前端·算法·easyui
秋子aria21 小时前
模块的原理及使用
前端·javascript
菜市口的跳脚长颌21 小时前
一个 Vite 打包配置,引发的问题—— global: 'globalThis'
前端·vue.js·vite
胖虎26521 小时前
实现无缝滚动无滚动条的 Element UI 表格(附完整代码)
前端·vue.js
小左OvO21 小时前
基于百度地图JSAPI Three的城市公交客流可视化(一)——线路客流
前端
星链引擎21 小时前
企业级智能聊天机器人 核心实现与场景落地
前端
GalaxyPokemon21 小时前
PlayerFeedback 插件开发日志
java·服务器·前端
爱加班的猫21 小时前
深入理解防抖与节流
前端·javascript
自由日记21 小时前
学习中小牢骚1
前端·javascript·css
泽泽爱旅行21 小时前
业务场景-opener.focus() 不聚焦解决
前端