为什么通过 innerHTML 注入的脚本没有执行,而元素上的 onerror 和其他 on<event> 属性是?- 谷歌 XSS 挑战 2

信息安全 xss javascript html
2021-08-11 04:41:05

剧透警告:如果您不想被剧透,请不要继续

我目前正在参加Google XSS Challenge Level 2

我正在使用插入到文档中的 XSS 代码注入element.innerHTML. 我不明白为什么<script>alert("Foobar")</script>不工作但<img src="/" onerror = "alert(1);"工作。

我试过查看源代码,但我仍然不明白为什么。我是 XSS 的新手,因此如果您在制定答案时参考源代码,我将不胜感激。

2个回答

答案取决于浏览器执行页面内不同位置的脚本的方式。例如:

  • 内联脚本标记中的 JavaScript 与网页中的其他标记同步处理。这些脚本标签可能会减慢网页的处理速度。
  • 在 DOM 加载后分配给元素的脚本标签(如挑战 2 的情况)实际上在大多数情况下从未执行(请参阅答案末尾的异常)!
  • 一旦特定事件发生,事件处理程序中的 JavaScript 作为属性就会立即执行(为什么输入喜欢<img src="/" onerror = "alert(1);"并且<body onload="alert(2)"></body>在这种情况下会起作用)。

例外:

defer在 DOM 完全渲染之前,不会执行带有属性的脚本标签(在某些浏览器上)。例如,我在 IE 上尝试了相同的挑战,并且能够使用以下用户输入来提醒弹出窗口:

<script defer>alert(2)</script>

通过 innerHTML 中的脚本标签注入到 DOM 的脚本在注入时不会运行(内联脚本在解析原始页面时运行)。另一方面,此时会加载注入到 DOM 中的图像,如果加载失败,则会调用 onerror 事件处理程序。