【问题标题】:Do I sanitize/escape correctly?我是否正确消毒/逃生?
【发布时间】:2013-04-14 14:18:54
【问题描述】:

我用 PHP 编写了一个简单的搜索脚本,它搜索 mySQL 数据库并输出结果。它的工作原理是这样的:

  • 用户通过搜索表单搜索“jack's”。
  • 我的 PHP 脚本 GETs 这个搜索,并清理它。
  • 然后脚本,使用SELECTLIKE,得到结果。
  • 脚本然后将结果输出给用户。
  • 最后,脚本告诉用户“jack 已返回 x 个结果”。在逃跑的帮助下。

我想问的是,我做得对吗?

这是我在 SELECTING 之前从数据库中清理的方式:

if(isset($_GET['q'])){
  if(strlen(trim($_GET['q'])) >= 2){
    $q = trim(mysql_real_escape_string(addcslashes($_GET['q'], '%_')));
    $sql = "SELECT name, age, address FROM book WHERE name LIKE '%".$q."%'";
  }
}

这就是我在输出“jack's returned x results”之前的转义方式。:

echo htmlspecialchars(stripslashes($q)) . " returned x results.";

这是正确的方法吗?

顺便说一句,我知道 PDO 和 mySQLi 是首选,因为它们通过使用准备好的语句进行自我消毒,但我对它们没有任何实际经验。但我很乐意看看,如果你们可以链接我一些新手教程/解释。 此外,我听说magic_quotescharset 可能会以某种方式导致注射——这是正确的吗?

【问题讨论】:

  • 您的转义以完全错误的顺序应用。也许解释一下你认为它会如何工作。
  • @mario 是吗?我不知道哪个顺序更好/更正确。还是让我解释一下。当脚本GETs 时,输入被修剪并检查输入是否等于或超过 2 个字符。然后,它首先通过在%_ 中添加斜杠以防止通配符搜索,然后通过使用mysql_real_escape_string 对输入进行清理,最后如果在开头或结尾有空格,它会修剪的输入。现在正在数据库中搜索它清理过的任何内容。至于转义——它有效,但我是从一个随机主题中得到的。
  • 嗯,首先进行修剪,然后是 m_r_e_s,然后为 LIKE glob 添加cslashes。
  • 好的。但是你能像我五岁一样解释一下,不同消毒功能的顺序有多重要吗?我的意思是..你能举例说明trim, m_r_e_s, addcslashes 的工作方式与addcslashes, m_r_e_s, trim 有何不同/更好?
  • 你能评论一下输出吗?我能正确地逃避它吗?我还需要htmlspecialchars 函数吗?或者可以用更好的东西代替吗?

标签: php mysql input output mysql-real-escape-string


【解决方案1】:

出于某种原因,我们也需要escape a backslash
所以,我相信正确的代码是

if(isset($_GET['q'])){
  $_GET['q'] = trim($_GET['q']);
  if(strlen($_GET['q']) >= 2){
    $q = $_GET['q'];
    $q = '%'.addCslashes($q, '\%_').'%';
    // now we have the value ready either for escaping or binding
    $q = mysql_real_escape_string($q);
    $sql = "SELECT name, age, address FROM book WHERE name LIKE '$q'";
    //or 
    $sql = "SELECT name, age, address FROM book WHERE name LIKE ?";
    $stm = $pdo->prepare($sql);
    $stm->execute(array($q));
    $data = $stm->fetchAll();
  }
}

对于输出,使用

echo htmlspecialchars($_GET['q']);

这里不需要带斜杠。

此外,我听说 magic_quotes 和 charset 可能会以某种方式导致注入 - 这是正确的吗?

如果您不使用魔术引号,它们不会损害您的安全。
charset 在一些极其罕见的编码的情况下是危险的,但只有在设置不正确的情况下。如果 mysql(i)_set_charset 或 DSN(在 PDO 的情况下)用于此目的 - 你又安全了。

对于 PDO,我相信 tag wiki 对于初学者来说应该足够了

【讨论】:

  • 感谢您的回答,但您提供的代码使事情变得更糟。首先,在 addCslashes 周围使用的 % 是无用的,因为这些可以在 SELECTING 时放置在 $q 周围(我这样做)。最后,输出需要使用带斜杠,否则它将返回“jack\'s returned x results”而不是“jack's returned x results”。总而言之,上面的代码与我的几乎相同——尽管你的代码添加了斜杠\的我要偷!
  • 很抱歉,您的两个想法都大错特错。将 %s 添加到变量后,您可以将其用于转义或绑定。我不会称之为“更糟”。从数据库中读取数据从不需要使用带斜线。如果您需要它,这意味着您的数据被魔法引号或其他任何错误代码破坏了。而且你必须清理它而不是使用stripslashes。
  • 我认为你在这里误解了一些东西(也许我在我的帖子中没有说清楚)。我的输出不是来自数据库(如您所说),而是来自用户输入的内容。所以是的,我在哪里添加 %s 很重要,并且使用带斜杠很重要,因为在输出的情况下我从数据库中读取数据。
  • 没错。为此,您需要 2 个变量。我很抱歉。更正了代码。
  • 没问题。顺便说一句,当我在输出中使用htmlspecialchars 时,似乎“Ömer”之类的东西没有出现,因为“ö”。这可能是因为一些相互矛盾的字符集设置吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-19
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
相关资源
最近更新 更多