前言
ps:我不知道文中手法新不新,但是对我来说,值得学习,也喜欢能和大佬学习更多有用东西.喵!
我喜欢以意想不到的方式使用JavaScript,构造出看似不能工作但是却正常运行的代码,或者会产生一些意想不到的行为。这可能听起来不算什么,但我发现的这些结果让我发现了一些非常有用的技巧。下面我所描述的每种技术都可以用来bypass xss filter
,这是我创造它们时的初衷。与此同时,学习这样的JavaScript可以显著提高您对该语言的了解,帮助您更好地处理用户输入,并提高Web应用程序的安全性。
RegExp替换可以执行代码
当使用正则表达式替换第二个参数时,支持函数分配。 在Opera中,似乎你可以使用这个参数来执行代码。 例如,请看下面的代码:
1.'XSS'.replace(/XSS/g,alert)
试过啦,完全ok:
看图:
通常你会使用一个函数在匹配的文本上执行另一个代码,如下所示:
1.somestring'.replace(/some/,function($1){//do something with some})
2.
我改了一下:
成功执行了.
但正如您在本节的第一个示例中所看到的,不是用户定义的函数,而是执行本地弹窗时调用,并且参数将从正则表达式传递给本地调用。 这是一个很酷的技巧,可以用来避开一些XSS过滤器,例如,如果你注入一个字符串,然后继续加点什么,你可以调用任何函数。
为了看看这是如何在XSS环境中使用的,假设我们有一个未经过滤的"
在发生注入的字符串中,比如JavaScript事件或脚本标记。首先我们注入我们的payload alert(1),然后我们把引号分离出来 ,引号 - " -
并继续我们的正则表达式:
1..replace(/.+/,eval)//
注意我在这里使用eval来执行我喜欢的任何代码,并且正则表达式匹配所有内容,以便将完整的payload传递给eval。
如果我将所有代码放在一起并向您显示页面的输出内容,则更容易理解正在发生的事情:
页面输出:
1.<script>somevariableUnfiltered="YOUR INPUT"</script>
2.
上述代码在您的搜索字符串由广告公司存储的分析脚本中很常见。 你经常看不到这些脚本,但是如果你查看网页的源代码,你会发现它们; 论坛是它们流行的另一个地方。"YOUR INPUT"
是您控制的字符串; 如果输入未被正确过滤,这也被称为基于DOM的XSS。
1.Input:
2.
3.alert(1)".replace(/.+/,eval)//
4.
5.Resulting output:
6.
7.<script>somevariableUnfiltered="alert(1)".replace(/.+/,eval)//"</script>
注意用于删除尾部引号的单行注释。
Unicode转义
虽然在转义unicode字符时不可能使用括号,但是您可以跳过被调用函数的名称,例如:
1.\u0061\u006c\u0065\u0072\u0074(1)
这调用alert(1); \u
表示这是一个Unicode转义符,并且后面的十六进制数字指定了该字符。 \ u0061
是a
,等等。
也可以混着用:
1.\u0061lert(1)
你也可以将它们包含在字符串中,例如使用eval。 Unicode转义与正常的十六进制或八进制转义不同,因为它们可以包含在字符串中,或者是对函数,变量或对象的引用。
下面的例子显示了如何使用eval并分割成不同部分的unicode转义符:
1.eval('\\u'+'0061'+'lert(1)')
通过避免像alert这样的正常函数名称,我们可以欺骗XSS过滤器来注入我们的代码。 这个例子被用来绕过PHPIDS(一个开源的IDS系统),这导致规则随后变得更加强大。 如果您在运行时考虑将JavaScript代码进行一些恶意攻击,您需要考虑怎么才可以让code工作; 正如你从这个例子中看到的那样,这不是一件容易的事。
JavaScript解析器引擎
JavaScript是一种非常动态的语言。 它可以执行因缺思厅的代码,表面上看起来并不合理,但是一旦你知道解析器是如何工作的,你就会开始理解它背后的逻辑。
一言不合表情包,咳咳.
JavaScript在执行之前并不知道函数的结果,显然它必须调用函数来返回变量类型。 这导致了一个有趣的怪癖 - 例如,如果返回函数没有为代码块返回有效值,则在执行该函数后会发生语法错误。
这在英语中意味着什么? 那么,能用代码说话就不要多bb,举个例子:
1.+alert(1)--
alert函数执行并返回undefined,但到那时为时已晚(先弹再执行后面的) - 递减运算符期待一个数字并因此产生错误。
还是弹了.
以下是一些更有效的例子,它们不会引发错误,但仍然很有趣。
1.+alert(1)
2.1/alert(1)
3.alert(1)>>>/abc/
您可能会认为上述示例毫无意义,但实际上它们提供了对Javascript工作方式的深入了解。 一旦你理解了这些小细节,大局上就会变得清晰,代码执行的方式可以帮助你理解解析器的工作方式。 在追踪语法错误和基于DOM的XSS以及利用XSS过滤器时,我发现这些类型的示例很有用。
Throw, Delete what?
您可以使用delete操作符的方式,这会导致一些非常古怪的语法。 让我们看看结合throw,delete,not和typeof运算符会发生什么?
1.throw delete~typeof~alert(1)
即使你认为它不可能工作,也可以在函数调用中调用delete并且它仍然执行:
1.delete alert(1)
更多板栗1.delete~[a=alert]/delete a(1)
2.delete [a=alert],delete a(1)
一开始,你会认为他们会提出一个语法错误,但是当进一步检查代码时,它很有意义。 解析器首先在数组内找到一个变量赋值,然后执行赋值然后删除该数组。 同样,删除是在函数调用之后执行的,因为它在删除返回的对象之前需要知道函数的结果,即使它为空。
再次,这些示例已被用来击败XSS过滤器,因为它们经常试图匹配有效的语法,并且他们不期望代码的模糊性质。 在编写应用程序做数据验证时,开发人员应该考虑这些示例.
全局对象
在有某些XSS过滤器的情况下,发送隐藏在向量中的类似英文的文本会很有用。 像PHPIDS这样的系统使用英文和向量比较来确定请求是否是攻击,因此它是测试这些系统的有效方法。
使用全局对象/函数可以生成类似英文的代码块,要了解它的工作原理,请查看以下示例:
1.stop, open, print && alert(1)
我创造了Javascriptlish这个名字,因为它有可能产生一些看起来很疯狂的代码:
1.javascript : /is/^{ a : ' weird ' }[' & wonderful ']/" language "
2.the_fun: ['never '] + stop['s']
我们使用运算符^的正则表达式/is/,然后创建一个对象 { a : ‘weird’}(它有一个属性a和一个奇怪的赋值)。然后我们在对象内寻找一个属性’ & wonderful ’ 我们刚刚创建,然后被一串语言分割。
接下来,我们使用一个名为the_fun的标签和一个永远不会使用的数组,使用名为stop的全局函数并检查s的属性……所有这些都是有效的语法。
Getters/Setters fun
当Firefox为设置者添加自定义语法时,它启用了一些不使用括号的有趣的XSS向量。 Opera目前还不支持自定义语法 - 从安全的角度来看,这不错,但从JavaScript Hacker
的角度来看并非如此。
Opera不支持标准的defineSetter语法。 这使我们可以通过任务调用函数,这仍然可以用于bypass XSS过滤器:
1.defineSetter('x',alert); x=1;
如果你不知道setter/getters,上面的例子为全局变量x创建一个setter。 无论什么时候变量被设置了一些东西,并且参数是从已经赋值的东西中提供的,都会调用setter。 第二个参数是要在分配时调用的函数,就是alert。 然后,当x被赋值为1时,alert函数以1作为参数被调用。
url encoding
location object允许在JavaScript代码中进行网址编码。 这允许您通过对它们进行双重编码来进一步混淆XSS向量。
1.location='javascript:%61%6c%65%72%74%28%31%29'
将它们与unicode转义相结合可以很好地隐藏字符串:
1.location='javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c %75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(1)'
第二个例子结合了第一种技术和前面提到的unicode escape技术。 所以,当你解码字符串时,它会产生unicode代表的弹框,就是\u0061\u006c\u0065\u0072\u0074.