【问题标题】:Sanitizing/Escaping user input and output清理/转义用户输入和输出
【发布时间】:2013-04-23 15:45:48
【问题描述】:

我知道我已经asked了一个关于消毒和逃逸的问题,但我有一个问题没有得到回答。

好的,就这样吧。如果我有一个 PHP 脚本并且我 GET 用户输入和 SELECT 它来自一个 mySQL 数据库,如果我没有通过使用来逃避 <> 是否有任何安全风险? htmlspecialcharshtmlentitiesstrip_tags,因此允许从数据库中选择/搜索 HTML 标签?因为输入已经通过使用trim()mysql_real_escape_stringaddcslashes (\%_) 进行了清理。

使用htmlspecialchars 的问题在于它转义了与号(&),这是用户输入应该允许的(我猜htmlentities 也是如此?)。通过使用strip_tags,类似“John”的内容会导致 PHP 脚本为 John 选择并显示结果,这是不应该的。

这是我的 PHP 代码,用于在从数据库中选择之前清理输入:

if(isset($_GET['query'])) {
  if(strlen(trim($_GET['query'])) >= 3) {
      $search = mysql_real_escape_string(addcslashes(trim($_GET['search']), '\%_'));
      $sql = "SELECT name, age, address WHERE name LIKE '%".$search."%'";
      [...]
  }
}

这是我显示“x 匹配 y 结果”的输出。

echo htmlspecialchars(strip_tags($_GET['search']), ENT_QUOTES, 'UTF-8')." matched y results.";

【问题讨论】:

  • 应该为您的目标环境进行清理/转义。 html 不能“影响” sql,因此将其保留在数据库中是安全的。事实上,最好不要转义,直到您检索它并尝试在浏览器上下文中显示它。如果您实际上是在寻找某些东西,这可以避免您不必转义,并消除双重转义的可能性,例如&
  • 好的,谢谢。所以,我所做的似乎足够正确,是吗?
  • 没有。你是不推荐使用的 mysql_*() 函数。切换到 mysqli 或 PDO。并删除 addcslashes() 调用。这是不必要的,只是为数据库中的数据添加了另一层毫无意义的转义。 mysql_real_escape_string 是您在查询中安全使用表单数据唯一需要的。
  • 我知道我正在使用已弃用的 mysql_*() 函数。正如我对@jball037 所说,我之前曾多次被建议过。但我只是想知道我上面提到的是否会削减它。顺便说一句,addcslashes 用于保护我的 PHP 脚本不显示数据库中的所有内容,因为mysql_real_escape_string(据我所知)不会转义通配符,例如%_ .我之所以在其中添加 ``,是因为搜索“John's”会在数据库中搜索“John's”,这不是这里的意图。
  • 您希望您的用户在搜索框中输入John\'s?那永远飞不起来。您让他们输入他们想要的任何内容,然后使用适当的转义将这些数据安全地放入查询中。请记住:mysql 在文本中实际上并没有 SAVE 反斜杠。它们作为查询解析阶段的一部分被删除。如果你有INSERT ... VALUES ('John\'s'),那么John's 是实际保存在数据库中的,而不是John\'s

标签: php mysql input output


【解决方案1】:

解决这个问题的一个好方法是使用 MySQLi,它使用准备好的语句,基本上可以为您在后端转义所有内容,并提供强大的 SQL 注入保护。不转义 GET 数据与不转义任何其他输入一样危险。

【讨论】:

  • 感谢您向我指出 MySQLi 函数。已经多次向我建议,我会尽快阅读。但是我想从 MySQL 到 MySQLi(或者为了 PDO)不是一夜之间就能完成的事情,对吧?
  • PDO 确实比 mysqli 有一些优势,特别是命名占位符。如果您没有太多数据库代码需要适应,它可以“一夜之间”完成。 Learning PDO 只需要半个小时左右。
  • 取决于你有多少代码(和 MySQL 查询)。您将所有当前的 MySQL 查询转换为 MySQLi 格式,但除此之外没有太多开销。我无法与 PDO 交谈,因为我对此一无所知 :)
  • 好吧,我的 PHP 脚本非常简单。它有一个表单输入,用户可以在其中搜索,然后将搜索结果显示给用户。它只有我的帖子中提到的 MySQL 查询。我想这会很容易吗?我一定会调查的。 :-)
【解决方案2】:

您在这里发现了两个不同的问题。

SQL 语句中的用户数据

无论何时构建查询,您都需要绝对确定不会出现任意用户数据。这些错误称为SQL injection bugs,是未能正确转义数据的结果。作为一般规则,您永远不应该使用字符串连接来组成查询。尽可能使用placeholders 确保您的数据被正确转义。

HTML 文档中的用户数据

当您呈现包含用户提交内容的页面时,您需要对其进行转义,以便用户无法引入任意 HTML 标记或脚本元素。这是避免XSS issues 并意味着像&< 这样的字符不会被错误地解释。 “x

对于将用户数据渲染到的任何上下文,您总是需要转义。还有其他的,比如在脚本标签中或在 URL 中,但这是最常见的两种。

【讨论】:

    猜你喜欢
    • 2011-02-23
    • 1970-01-01
    • 2013-09-14
    • 1970-01-01
    • 2014-01-31
    • 2012-10-02
    • 2014-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多