前段时间在学习各位大佬的文章的时候,遇到了一个XSS的payload,根据文章的表述可以得知该payload是经过UTF-8编码的。解码后地道初始payload,然并卵,还是看不懂。
UTF-8 编码后的payload
[]["\146\151\154\164\145\162"]["\143\157\156\163\164\162\165\143\164\157\162"]("\145\166\141\154\50\141\164\157\142\50\42\131\127\170\154\143\156\121\157\115\123\153\75\42\51\51")()
原始payload
[]["filter"]["constructor"]("alert(1)")()
JavaScript 试图帮助我们将一些数据类型转化为我们所认为的数据类型,例如我们定义一个字符串常量,它会假设我们希望添加的是文本形式,所以 JavaScript 会把它转化为字符串类型。
javascript中有一些的特殊的符号,可以用来干扰我们定义的内容被javascript认为的数据类型,使用这些符号,我们就可以拼凑和魔改出,看起来乱七八糟,实际上真实有效的XSS攻击载荷。
举例
以 “+” 或者"-" 为前缀,那么javascript 会认为我们需要它以数字形式表示,甚至在合适的情况下,会将字符串也用数字表示。以"!"非这个符号为前缀,那么它会将我们的内容转换为布尔格式。
我们可以用[、]、(、)、+、!这六个符号来做一些神奇的事情,JSFuck也是基于这几个符号拼凑起来,以表示各种各样的内容的
首先需要记住以下几点
示例,可以在浏览器的控制台敲除,看看结果;这里补充一个小提示:JS中使用"“时,如果两边类型不同,js引擎会把它们转换成相同类型然后在进行比较,而”="则不会进行类型转换,因此当两边不是属于同一个类型,肯定不相等。
![] === false
[]+[] ===""
+[] === 0
同时,在js中,字符串可以像数组一样的获取对应的值。
"hello"[0] ==="h"
可以通过小括号,来进行先后运算循序的确定,
+("1"+"1") ==11 //首先是字符串的拼接,然后是+前缀,将字符串转换为了数字
通过以下内容可以得到字符a
//首先得到false字符串
![]
[]+![]
//然后得到1这个数字
+!![]
//最后得到字符a
([]+![])[+!![]]
所以,我们利用上述字符的一些简单组合就可以得到「 true 」和「 false 」中的字母,比如「 t 」「 r 」「 u 」「 e 」「 f 」「 a 」「 l 」「 s 」。那么我们可以得到其他字母吗?
当然,我们可以通过「 [ 」「 ] 」的简单组合来得到「undefined」,也就是说利用刚提到的黄金法则,我们又得到了「 d 」「 i 」「 n 」三个字母。
通过这种特殊的组合,得到各种字母,最后拼接,表示各种函数、字符串等,这就是JSFuck,但是本文的重点在于弄明白文章开头所说的payload是如何生效的。
[]["filter"]["constructor"]("alert(1)")()
[]["name"] //表示name函数
constructor 方法被所有 JavaScript 对象所共有,而且它会返回构建该对象的函数。
例如
true["constructor"] + [] === "function Boolean() { [native code] }"
0["constructor"] + [] === "function Number() { [native code] }"
""["constructor"] + [] === "function String() { [native code] }"
[]["constructor"] + [] === "function Array() { [native code] }"
而payload 中使用这个方法的原因是为了填充内容,
[][“filter”][ “constructor”](“alert(1)”), 是一个匿名函数里面填充alert()
不加这个方法是不行,会报错
payload 最后面的"()"则是表示即刻调用该函数。才能触发弹窗。
https://zhuanlan.zhihu.com/p/22948500
https://shellbr3ak.medium.com/xss-waf-bypass-128e8b4167fb