题目
function escape(input) {
// v-- frowny face
input = input.replace(/[=(]/g, '');
// ok seriously, disallows equal signs and open parenthesis
return input;
}
解题思路
正则把输入内容中所有 =
和 (
过滤了。
=
被过滤了不是什么大问题,XSS 直接放在 <script>
标签一样可以执行,关键是 (
被过略了。
此处可以利用 <svg>
标签【会对标签中的内容优先做实体编码解析】的原理进行绕过。
在网页编码中,以
&#ASCII;
称为实体编码,其中 ASCII 可以用十进制或十六进制表示。如(
的 ASCII 编码为 40 (或十六进制 0x28) ,那么(
或(
就是(
的实体编码。
因此这题可构造这样的 payload 实现绕过:<svg><script>prompt(1)</script>
。
它的工作原理为:
- 在 HTML 中,原本
<script>
标签属于 Raw text elements ,其内部文本遵循着不转义的规则。 - 但是
<svg>
标签属于 Foreign Elements ,即使在HTML语境下也不会受到 HTML 规则的影响,而是遵循<svg>
自身的解析规则。 - 而
<svg>
直接继承自 XML,一般情况下,它的解析规则为:除非被 CDATA 包围,否则实体编码都会被转义。
这题也可以利用 javascript 的 eval 函数实现绕过,payload 如下:
<script>eval.call`${'prompt\x281)'}`</script>