什么是HTML转义上下文?

时间:2009-12-15 22:51:25

标签: html escaping

输出HTML时,有几个不同的地方可以将文本解释为控制字符而不是文本文字。例如,在“常规”文本中(即,在任何元素标记之外):

<div>This is regular text</div>

以及属性值:

<input value="this is value text">

而且,我相信,在HTML评论中:

<!-- This text here might be programmatically generated
and could, in theory, contain the double-hyphen character
sequence, which is verboten inside comments -->

这三种文本中的每一种都有不同的规则,规定如何将其转义以便将其视为非标记。所以我的第一个问题是,HTML中是否还有其他任何字符可以解释为标记/控制字符?上述情况显然对于需要转移的内容有不同的规则。

第二个问题是,为了确保任何嵌入的文本都被视为非标记,需要转义的规范的,全局安全的字符列表(对于每个上下文)是什么?例如,理论上你只需要在属性值中转义'和',因为在属性值中只有结束分隔符('或“取决于属性值的起始符号)有控制意义。类似地,仅在“常规”文本中&lt;和&amp;有控制意义。 (我意识到并非所有HTML解析器都是相同的。我最感兴趣的是为了安抚符合规范的解析器而需要转义的最小字符集是什么。)

切向:以下文本将抛出错误,因为HTML 4.01严格:

<a href="http://example.com/file.php?x=1&y=2">foo</a>

具体来说,它说它不知道实体“&amp; y”应该是什么。如果你在&amp;之后放一个空格,那么它验证就好了。但是,如果你在飞行中产生这个,你可能不想检查是否每次使用&amp;会导致验证错误,而只是逃避所有&amp;内部属性值。

5 个答案:

答案 0 :(得分:11)

<div>This is regular text</div>

文字内容:&必须转义。必须转义<

如果使用非UTF编码生成文档,则必须转义不符合所选编码的字符。

在XHTML(和一般的XML)中,序列]]>不得出现在文本内容中,因此在该特定情况下,必须对该序列中的一个字符进行转义,传统上为>。为了保持一致性,Canonical XML规范选择每次在文本内容中转义>,这对于转义函数来说并不是一个糟糕的策略,尽管你可以跳过它来进行手工创作。

<input value="this is value text">

属性值:&必须转义。必须转义属性值分隔符"'。如果没有使用属性值分隔符(不要这样做),则无法进行转义。

Canonical XML总是选择"作为分隔符,因此将其转义。 >字符不需要在属性值中进行转义,而Canonical XML则不需要。 HTML4规范建议编码>无论如何都要向后兼容,但这只影响了一些现在没人记得的真正古老而可怕的浏览器;你可以忽略它。

在XHTML <中必须进行转义。虽然你可以在HTML4中逃避它,但这不是一个好主意。

要在属性值中包含制表符,CR或LF(不通过属性值规范化算法将它们转换为普通空格),必须将它们编码为字符引用。

对于文本内容和属性值:在XML 1.1下的XHTML中,必须转义受限字符,即删除字符和C0和C1控制代码,减去制表符,CR,LF和NEL。总共[\x01-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F]。即使在XML 1.1中转义,也可能根本不包含空字符。在XML 1.1之外,你根本不能使用任何这些字符,也没有一个你想要的理由。

<!-- This text here might be programmatically generated
and could, in theory, contain the double-hyphen character
sequence, which is verboten inside comments -->

是的,但由于内部评论中没有可能的转义,因此您无能为力。如果你写<!-- &lt; -->,它的字面意思是包含“&符号字母t-分号”的注释,并将在DOM或其​​他信息集中反映出来。包含--的评论根本无法序列化。

XML中的

<![CDATA[个部分和<?pi也无法使用转义。串行化包括]]>序列的CDATA部分的传统解决方案是将该序列分割为两个CDATA部分,因此它不会一起发生。您无法在单个CDATA部分中对其进行序列化,也无法在数据中使用?>序列化PI。

HTML(非XHTML)中的<script><style>等CDATA元素可能不包含</(ETAGO)序列,因为这会提前结束元素,如果不遵循则会出错通过end-tag-name。由于在CDATA元素中不可能进行转义,因此必须避免和解决此序列(例如,将document.write('</p>')转换为document.write('<\/p>');。(您会看到许多更复杂的愚蠢策略来解决这个问题) ,就像在JS - %编码的字符串上调用unescape一样;甚至经常'</scr'+'ipt>'仍然非常无效。)

HTML和XML中还有一个上下文,其中适用不同的规则,并且在DTD中(包括DOCTYPE声明中的内部子集,如果有的话),其中%字符具有特殊权力和需要转义才能按字面意思使用。但作为一个HTML文档作者,你几乎不可能在任何地方接近整个混乱。

The following text will throw errors as HTML 4.01 Strict:

<a href="http://example.com/file.php?x=1&y=2">foo</a>

是的,这在Transitional中也是一个错误。

If you put a space after the &, however, it validates just fine. 

是的,根据SGML规则,除[A-Za-z]#之外的任何内容都不会开始解析为引用。尽管如此依靠这个并不是一个好主意。 (当然,它在XHTML中并不是很好。)

答案 1 :(得分:1)

  

上述情况显然对于需要转义的内容有不同的规则。

我不确定不同的元素有不同的编码规则。您列出的所有示例都需要HTML编码。

E.g。

<h1>Fish &amp; Chips</h1>
<img alt="Awesome picture of Meat Pie &amp; Chips" />
<a href="products.aspx?type=1&amp;meal=fish%20%26%20chips&amp;page=1">Fish &amp; Chips</a>

最后一个示例包括一些&符号的URL编码(&amp;),此时它会变得毛茸茸(发送&符号作为数据,这就是必须编码的原因)。

  

所以我的第一个问题是,HTML中是否有其他上下文可以将字符解释为标记/控制字符?

HTML文档中的任何地方,如果控制字符未被用作控制字符,则应对其进行编码(作为一个好的经验法则)。大多数时候,它的HTML编码,&amp;或者&gt; Othertimes,当试图通过URL传递这些字符时,使用URL编码%20,%26等。

  

第二个问题是,为了确保任何嵌入的文本都被视为非标记,需要转义的规范,全局安全的字符列表(对于每个上下文)是什么?

我会说Wikipedia article对它有一些好的评论,可能值得一读 - 而W3 Schools article我认为这是一个好点。大多数语言都内置了将文本准备为安全HTML的函数,因此可能值得检查您选择的语言(如果您确实使用任何脚本语言而不是手工编写HTML)。

具体来说,维基百科说:“人物&lt ;,&gt;,”和&amp;用于分隔标签,属性值和字符引用。字符实体引用&amp; lt;,&amp; gt;,&amp; quot;在HTML,XML和SGML中预定义的和&amp; amp;可以代替字符的文字表示。“

对于网址编码,this article seems a good starting point

关闭思路,因为我已经絮絮叨叨了一下:这完全排除了XML / XHTML的想法,它给法院带来了另一个球赛,并要求几乎世界及其狗需要编码。如果您正在使用脚本语言并通过它编写变量,我很确定找到内置函数会更容易,或者下载一个可以为您执行此操作的库。 :)我希望这个答案是确定的,并没有错过任何观点或问题或错误的语气。 :)

答案 2 :(得分:1)

如果您正在寻找在Web浏览器中转义字符的最佳做法(包括HTML,JavaScript和样式表),Michael Coates的XSS预防备忘单可能就是您所需要的。它包括对不同解释上下文的描述,表示如何在每个上下文中编码字符的表和代码样本(使用ESAPI)。

http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

答案 3 :(得分:0)

如果您担心最终HTML的有效性,可以考虑通过DOM构建HTML,而不是文本。

您没有说明您要定位的环境。

答案 4 :(得分:0)

请注意,<script>后跟<!--后跟<script>,再次进入双重转义状态,您可能永远不会想要这样,所以理想情况下你应该逃避<在脚本的字符串(和正则表达式)中使用“\ u003C”不会意外触发它。

您可以在此处详细了解http://qbolec-memdump.blogspot.com/2013/11/script-tag-content-madness.html