如果正在检索的数据已经过清理,是否需要从 MySQL 服务器转义输出?

Is escaping output from MySQL server necessary if data being retrieved has already been sanitized?

如果用户提交表单时检索到的数据已经被过滤,我想知道是否有必要对 MySQL 服务器的输出进行转义。

示例:
1. 用户提交带有博客评论的表单 post.
2. 在提交表单时,在将数据发送到 MySQL 服务器之前,他们的输入会使用 FILTER_SANITIZE_SPECIAL_CHARS 进行过滤以防止注入攻击。
3. 一旦数据被post发送到服务器,用户将被重新路由到另一个屏幕,他们可以在其中查看他们的评论。
4. 当从服务器(存储了过滤后的输入)中检索他们的评论时,是否也需要对这个输出进行转义?

这是我的主要问题。我正在从表单中获取用户输入(对于博客 post),使用 FILTER_SANITIZE_SPECIAL_CHARS 对其进行清理,然后 post 将其发送到 MySQL 服务器。如果我从服务器检索此信息并将其显示在 html 中,则没有问题。但是,我一直在读到您也应该始终转义服务器的输出。所以我用htmlspecialchars()逃脱了同样的post。现在,我遇到的问题是所有特殊字符(包括括号,以及用户在 post 中使用的任何引号)都以转义的 html 格式返回。一点都不用户友好。

对此最好的解决方法是什么,或者如果输出来自服务器并且已经对用户输入进行了清理,是否有必要对输出进行转义?

清理与转义不同,您应该确保不要混淆两者。

清理 正在删除不需要的输入。也就是说,如果用户在他们的输入中添加了一个 <script> 标签,而您不希望他们的输入包含 <script> 标签,那么删除该 <script> 标签就是清理。清理不是转义输出上下文的数据。

Escaping 正在为输出上下文正确编码数据。例如,为了防止 HTML 注入,您可以调用 htmlspecialchars()& 正确编码为 &amp;。为防止 SQL 注入,您可以使用 mysqli::real_escape_string()' 转换为 \'。 (尽管 高度 更可取的是使用准备好的语句/参数化查询来避免担心 sql 注入或转义。)

重要的是,转义是特定于上下文的。您用于 HTML 的转义不一定对 SQL 有效或足够(反之亦然,或任何其他输出上下文)。

FILTER_SANITIZE_SPECIAL_CHARS 的问题在于它的命名不当:它在一步中同时完成这两项工作,这会使您的数据库感到困惑(因为您的数据库现在有 html 编码的数据),并且混淆输出(因为现在你已经转义了容易被多重转义的数据)。

相反,您应该明确地将清理和转义工作分开。 清理您不想保留的输入数据。 转义输出数据,并根据其正确的输出上下文。

你想在数据库中存储原始(预输出转义)数据的原因是,如果你需要输出到不同的上下文(例如,现在你是东 JSON 输出,或者您需要将其写入文件,或者实际查看原始数据是什么),您不需要先取消转义。 (如果你真的需要,你可以合理地将预转义副本存储在单独的列中,但你应该始终保持原始数据可用。)它也使规则变得简单:始终清理输入;总是转义输出。