在显示用户生成/提交的信息时,转义其他特殊字符但不触及与号是否存在任何安全风险?我想让我的用户自由输入 html 实体、十六进制和十进制特殊字符,而不会给我的消毒剂增加不必要的复杂性。
2 回答
这完全取决于数据放入的上下文。
&
在 HTML 中,用字符引用表示纯文本的主要原因是避免歧义,因为&
也是这种字符引用的开始。这种歧义的一个流行示例是&
作为 HTML 属性中 URL 参数的一部分的纯文本,如下所示:
<a href="/?lang=en§=foobar">
这里&
没有使用相应的字符引用进行适当的编码,因此解析器将其视为字符引用的开始。并且由于sect是HTML 中的已知实体,表示节字符 §
,因此该属性值实际上被解释为/?lang=en§=foobar
.
因此,保持&
原样不会像 HTML 中的其他特殊字符那样造成实际威胁,因为它们可以更改数据放入的上下文:
- 标签分隔符
<
,>
可以开始或结束标签声明, - 属性值分隔符
"
,并且'
可以开始或结束属性值声明。
为了安全起见,您应该使用htmlspecialchars
double_encode参数集false
来避免对已经存在的字符引用进行双重编码:
var_dump(htmlspecialchars('<"&\'>', ENT_QUOTES, 'UTF-8', false) === '<"&'>'); // bool(true)
tldr; 如果编码正确,留下与号(或其他“特殊字符”)不是安全问题。也就是说,输出/使用很重要,而不是输入。
这一切都取决于最终如何使用数据。例如,对于任意输入,执行 a<input value="<? echo $input ?>" />
的编码不正确。
现在 an&
通常比其他一些字符(例如 , 或 )少得多的“问题” '
,但"
在某些情况下它可能会导致一些伪影(包括错误和未定义的行为),或者可能用于添加额外的查询参数一个网址<
>
- .. 但是如果在输出时URL 没有被适当编码,那么它的编码不正确 1
- .. 当然,如果 a
&
被逐字写入 XML/HTML 流,那么它的编码不正确 2 - ..如果程序将原始
&
[来自用户输入]传递给“shell字符串执行”,那么它[很可能]没有正确编码 3 - ..这一切都归结为使用。
我倾向于不更改输入,除非使其符合业务规则 - 这不包括上述情况!(但完全不接受&符号可能是一个完全有效的业务规则。)
在适当的时间进行适当的转义(或者,更好的是,不需要 [手动] 转义的方法)会处理其余部分,并确保通过对用法的良好编码,减轻琐碎的攻击或意外错误。
事实上,我认为这种“输入清理”表明对其他地方使用的方法/代码缺乏信任,并可能导致需要撤消“清理”的更多问题。魔术引用任何人?
1这是&
用户输入中的 an 实际上会导致某种形式的注入的情况。想象一下:format("http://site/view={0}", user_input)
,其中user_input
包含1&buy=1
。结果将是"http://site/view=1&buy=1"
。正确的方法是对值进行URI 编码(也称为百分比编码),这将导致"http://site/view=1%26buy%3D1"
. (请注意,在正确编码的情况下只有一个查询参数。如果意图是能够允许“原始”输入通过,那么仔细定义/分析允许的规则并参见以下段落。)
2虽然“裸”&
在 HTML 流中可能是有效的,但不应将用户输入视为“有效的 HTML”。也就是说,无论以 XML 还是 HTML 为目标,都应该使用正确的输出/呈现转义机制。(转义机制可能选择不编码“bare” &
,但这是次要问题。懒惰的程序员将继续对所有适用的输出使用相同的转义技术,以获得一致、可靠和安全的输出。)
3不要使用带有必须解析的单个参数字符串的 shell-execute,而是使用带有参数列表的 exec-form。后者 [通常] 防止产生 shell 和相关的 shell-hacks。而且,当然,永远不要让用户手动指定可执行文件..