XSS 进阶技巧之不能使用括号的时候如何构造 payload
2022-11-21 15:06:43358浏览
很多 XSS 靶场都是使用 alert(1) 来判定过关与否,但是在 CTF 比赛或者渗透场景中,我们都可能会遇到不能带入括号的情况,要么是出题方故意过滤掉了圆括号,要么是圆括号会影响 payload 的解析。

一、所用靶场

1. 靶场地址

这里使用的是易锦网校自己的 XSS 靶场,靶场地址: http://lab.yijincc.com:50008/?lesson=6

2. 靶场玩法

2.1 漏洞简述

这个区域下面的文字是对当前关卡的描述,如果题目比较难的话,出题人会在这里给一些暗示(大概是怕被骂吧)。

2.2 导致漏洞的代码

这个区域贴出来的 JavaScript 代码用于处理你输入的内容,这些内容经过处理才会渲染到子页面里面去,所有造成漏洞和过滤内容的代码都在这里有所体现。

但其实只有关键代码,而不是全部代码,如果过多的话会,干扰你的阅读(是不是很贴心)。

2.3 payload 输入区域

当你在一个 CTF 靶场中看到一个输入框,该干什么就不用多言了吧。

2.4 处理后的代码

你输入的内容经过处理之后的样子,渲染到子页面的内容就是长这个样子的,仔细观察你的输入对这里输出内容的影响,可以得出通关的关键。

2.5 渲染出来的页面

为了判定你是否通关,需要把内容渲染出来,这个区域就是一个专门用来渲染输出之后的内容的子页面。

如果你嫌子页面太小看不清楚的话可以点“全屏”按钮把它放大,再点击“退出全屏”按钮退出来。

2.6 通关条件

子页面里面的 window.alert 函数已经被改写,只要你成功地执行了 alert 函数,页面就会判定你通关。通关之后,页面上方的标题右边会渲染一个“下一关”按钮,点击按钮即可进入下一关。

3. 本文描述的是第六关

由于前面几个关卡都比较简单,所以这里我就不写题解了,如果你在中间的哪一个关卡遇到麻烦了,一定要多动脑筋、多百度,这样才能加深你的印象。

如果你连这些都尝试了还是不行的话,就去问问你的答疑老师。

二、解题描述

1. 阅读描述

……Markdown 通常会被生成为 HTML,然后直接渲染到网页,这就导致了:即便使用了框架,也很难规避其中的 XSS 代码隐患。

👆从这里我们可以得知一个事实:这个漏洞与 markdown 有关系,这一篇锦囊中我们大致科普了一下 markdown 语法,所以本篇不再赘述。

2. 查看代码

我知道对于大部分人而言,阅读代码是非常麻烦乃至于困难的事情,不过出题人显然不希望被你们骂到狗血淋头,所以在代码的关键地方都加了注释:

👆可以看出来这里使用的是标准 markdown 语法,随便百度一下都可以搜到的。

但是我么经常用来构造闭合的 <'" 都已经被提前替换了,所以破题的关键肯定就是 markdown 语法的部分。

3. 尝试一下

分别尝试一下链接语法和图片语法


[易锦网校](ke.yijincc.com)
![易锦图标](http://lab.yijincc.com:50008/logo192.png)

可以看到,正常渲染👇

👆但是渲染出了我们梦寐以求的双引号,只要找到方法加以利用,事儿就成了!

4. 正则表达式一生之敌——嵌套

上面的代码使用了正则表达式来匹配并替换代码,但是正则表达式的缺点就是不能嵌套解析,所以首先考虑嵌套使用语法。

如果你不知道什么是正则表达式,也不用担心——总而言之,CTF 中凡是遇到奇怪的解析规则的时候,先用嵌套试探一下解析器的底线准没错。

所以我们尝试在图片语法里面链接一个图片语法:

![[1](2) ](http://lab.yijincc.com:50008/logo192.png)

👆上面的红色部分是外面的图片语法,白色部分是套在里面的链接语法,如果你没领会到我的意思,把里面白色部分删除,换成数字 1 ,就明白了。

处理之后的代码有点奇怪:

👆可以看到 a 标签被“吞”进了 img 标签里面,说明我们的嵌套语法威力无穷。

5. 确定 payload 的插入点

老办法,我们先看一下双引号的配对情况,通常而言,属性 payload 应该放在最后一对引号后面某个位置(位置不对可以使用空格来调整),我们先数一下有哪些引号是成双成对的:

👆可以发现有两对,最后一个双引号落了单,经过检查,“落单的”引号对应的内容是链接语法的地址,也就是 [](2) 这句代码的 2 ,那么我们就在里面换成 onerror 属性以带入 alert:

![  [1](onerror=alert())  ](http://lab.yijincc.com:50008/logo192.png)

然而奇迹并没有如约而至:

6. 总算到本篇重点了——不使用括号执行 alert

仔细观察我们输入的东西,你会发现罪魁祸首是 alert() 里面的圆括号,因为图片语法和链接语法都需要识别圆括号,一旦你加了一个圆括号,就会重新破坏它们的结构——所以我们需要把 payload 中的括号先去掉。

7. 两个全新的知识点

  • JS 中的 setTimeout 可以把紧跟其后的字符串当成代码来执行;
  • 上述方法执行的代码可以使用 \x 编码,右括号的编码是 \x29。

8. 决战时刻

基于上面两个全新的知识点,我们修改一下 payload :

![  [1](onerror=setTimeout`alert(\x29`)  ](http://lab.yijincc.com:50008/logo192.png)

但是效果并没有出来,其实这是因为 payload 后面紧跟着一个双引号造成了语法错误:

这个问题很好解决,在 payload 尾巴上加一个空格就搞定了:

![  [1](onerror=setTimeout`alert(\x29` )  ](http://lab.yijincc.com:50008/logo192.png)

怎么回事?还是没有反应?——不要慌张,因为我们这里使用的是一个可以加载的图片,所以应该把 onerror 改成 onload ,通关!

![  [1](onload=setTimeout`alert(\x29` )  ](http://lab.yijincc.com:50008/logo192.png)

友情链接: