取消转义用户输入的符号是否安全?

Is it safe to unescape ampersand for user input?

经过几个小时的 bug 搜索,我找到了我最讨厌的 bug 之一的原因。

当用户在我的网站上输入消息时,他们可以使用纯文本和 html 实体为其命名。

这意味着在某些情况下,用户会输入带有常见 html 实体图片的标题,例如这张脸。 ( ͡° ͜ʖ ͡°).

为了防止html注入,我使用htmlspecialchars();在标题上,令人讨厌的是,当稍后输出到页面上时,它会将图片转换为 html 实体格式。

( ͡° ͜ʖ ͡°)

我意识到这里的问题是标题被编码为上面的例子,htmlspecialchar,以及做我想做的和编码可能的 html 注入,正在转向实体中的符号

&. 

通过 un-escaping 所有的符号,并将它们改回 & 这解决了我的问题,并且脸部会按预期出现。

但是我不确定这是否仍然可以免受恶意攻击 html。解码用户推定的标题中的符号是否安全?如果没有,我该如何解决这个问题?

没有直接的答案。您可能会将 &lt;script...&gt; 转义为 <script...> 并以麻烦告终,但看起来代码已被双重编码 - 可能在输入时一次,然后在输出到屏幕时再次编码。如果你能保证它已经过双重编码,那么撤消其中一个应该是安全的。

但是,最好的解决办法是将"raw"值保存在内存中,sanitize/encode用于输出到数据库,html,JSON等

因此 - 当您获得输入时,将其清除为您不需要的任何内容,但实际上不要将其转换为 HTML 或转义它或在此阶段进行任何其他操作。将其转义到数据库中,html 在输出到屏幕时对其进行编码/xml 等

如果您的实体显示为文本,那么您可能调用了 htmlspecialchars() 两次。

如果您没有明确调用 htmlspecialchars() 两次,那么如果包含表单的页面使用过时的单字节编码(如 [=34=),则可能会发生浏览器端自动转义]-1252。这种自动转义是正确表示特定单字节编码字符集中不存在的字符的唯一方法。所有当前的浏览器(包括 Firefox、Opera 和 IE)都这样做。

确保您使用的是 Unicode(尤其是 UTF-8)编码。

要使用 Unicode 作为编码,请将 <meta charset="utf-8" /> 元素添加到包含表单的 HTML 页面的 HEAD 部分。并且不要忘记以 UTF-8 编码保存 HTML 页面本身。要在 PHP 中使用 Unicode,通常使用 multibyte (mb_ prefixed) string functions 就足够了。最后,像 MySQL 这样的数据库引擎很久以前就支持 UTF-8。

作为临时解决方法,您可以通过将 htmlspecialchars() 函数的第 4 个参数 ($double_encode) 设置为 false.

来禁用对现有实体的重新编码