DEMO
<script>alert(1)</script>
<svg>
<script>alert(2)</script>
</svg>
一句话总结:HTML 在解析 svg 节点下的 script 时,会暂停原有html标准解析,并使用xml标准解析svg-script,导致了实体引用被解析执行。
另外可查到的相关问题:Why does this XSS vector work in svg but not in HTML?
相关内容
html element
在 html 中分为五类元素
- Void elements:空元素
area, base, br, col, command, embed, hr, img, input, keygen, link, meta, param, source, track, wbr - Raw text elements:原始文本元素
script, style - RCDATA elements: RCDATA元素
textarea, title - Foreign elements:外部元素
MathML命名空间、SVG命名空间中的元素. - Normal elements:基本元素
除了以上提到的元素以外的其他元素
区别如下:
- 空元素:不能容纳任何内容(因为没有闭合标签(end tag),所以无法在开始标签和闭合标签中间防止内容)
- 原始文本元素:可以容纳Unicode字符组成的文本,但不允许包含
</
开头的一系列内容 - RCDATA元素:可以容纳text 以及字符引用,但不能含有意义不明的
&符号
,除此外同上不允许包含</
开头的一系列内容 - 外部元素:当开始标签自动闭合时,不能包含任何内容(因为没有结束标签(end tag),所以不能在开始标签和结束标签之间放内容),当开始标签不自闭合时,其内容可以包含文本、字符引用、CDATA块、其他元素和注释,但是文本不能包含编码为U+003C的小于符号(<)或者意义不明的
&符号
。 - 基本元素:可以包含文本、字符引用、其他元素以及注释,但是文本不能包含编码为U+003C的小于符号(<)或者意义不明的
&符号
。在内容模型和本章节的给出的限制之外,有些常规元素在可以包含的内容方面有额外的限制。
剩下内容可见参考资料[1]一篇很好的文章
HTML script parse
html词法解析文档:html parsing
在接收到 script 标签后,进入script data state(脚本数据状态)
继续往下跟随,会发现怎么都无法进入Character reference state(字符引用状态)
,即无法解析被实体化编码后的内容
簡單總結一下,當<script>沒有做編碼時,會將script整體作爲一個token釋放,然後就會進入script data state狀態;但是如果編碼後,就會將script看成文本,拆成一個一個字符釋放(轉義後爲s作爲token釋放,又進入字符引用狀態,繼續轉義後爲c作爲token釋放,……,最後是t),所以到最後也沒進入script data state狀態,也就是沒有執行環境。
要想执行 script 意味着必须要在data state
状态下跟入script
标签进入script data stat
data state
+<script>
->script data state
那肯定就会有人问为什么 Unicode 编码可以呢
因为这又涉及了 JavaScript 标准(JavaScript 是由 Ecma 标准化的,标准叫 ECMAScript)
这里可以看到 JS 允许标识符名称使用 Unicode 字符,支持Unicode转义字符\u000A\u000B
,但不支持Unicode转义序列串\u000A000B
,具体规则可以去看一下
这样就能理解为什么下面的代码会执行了
<script>\u0061\u006c\u0065\u0072\u0074(10);</script>
实际感觉多读读标准文档理解渲染机制就能解决很多问题
script in svg
简单看一下就大致能明白主体意思
为什么实体编码会被解析
经过查找后,发现还存在一个 vxml,形式上和 svg 有些类似,但是在 vxml-script 中的 Html 实体编码就不会被解析出来
如果说 <svg> 是满足 xml 和 svg,利用 svg 支持 script,xml 支持实体编码,那么为什么类似的<vxml>不行呢?
在 html 解析文档中可以看到这个内容,当 script 标签节点出现在 svg 节点时,会挂起 html解析并根据 svg 标准进行进一步解析,这就导致了实体引用被解码
html解析 -> 发现svg-script -> svg(xml)解析 -> html解析继续
挑战赛答案
延伸
Content-Type:application/xml
<script xmlns="http://www.w3.org/2000/svg">alert(1)</script>