PDO/准备语句/白名单/设置字符集,是否足够安全以防止注入?

Ber*_*rdA 4 php mysql pdo sql-injection

我正在从扩展 mysql 转换为 PDO,在阅读了各位专家在 Stack\xc2\xa0Overflow 和其他地方的所有内容后,我还有一些剩余的问题。我想出了以下方法来解决典型查询的SQL 注入问题。我只是想知道这是否足够,或者在我将其复制到我的所有应用程序之前,我对白名单的处理可能有点过头了。

\n

我不清楚我是否正确地加入了白名单,即我是否也应该以某种方式逃脱。

\n

另外,我不确定是否应该为每个查询将 setAttribute 模拟为 false,或者只为脚本设置一次。

\n
$link = new PDO("mysql:host=$hostname;dbname=$database;charset=utf8", $username, $password);\n\n$link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);\n\n$arr_i = $arr_k = \'\';\n$m_act = $v_act = \'Y\';\n$table = array(\'prices\', \'versions\', \'models\');\n$allowedTables = array(\'prices\', \'versions\', \'models\');\n$field = array(\'model_id\', \'version_id\', \'price\', \'models.active\', \'versions.active\');\n$allowedFields = array(\'model_id\', \'version_id\', \'price\', \'models.active\', \'versions.active\');\n\nif(count(array_diff($field, $allowedFields))==0 AND count(array_diff($table, $allowedTables))==0) {\n\n    $sql = "SELECT COUNT(DISTINCT `" . $field[0] . "`) as ctmod FROM `" . $table[0] . "`\n            INNER JOIN `" . $table[1] . "` USING (`" . $field[1] . "`)\n            INNER JOIN `" . $table[2] . "` USING (`" . $field[0] . "`)\n            WHERE `" . $field[2] . "` BETWEEN :arr_i AND :arr_k\n            AND " . $field[3] . " = :m_act\n            AND " . $field[4] . " = :v_act";\n\n    $stmt = $link->prepare($sql);\n    $stmt->bindParam(\':arr_i\', $arr_i, PDO::PARAM_INT);\n    $stmt->bindParam(\':arr_k\', $arr_k, PDO::PARAM_INT);\n    $stmt->bindParam(\':m_act\', $m_act, PDO::PARAM_STR);\n    $stmt->bindParam(\':v_act\', $v_act, PDO::PARAM_STR);\n    for ($i=0; $i < $ctpri; $i++) {\n        $k = $i + 1;\n        $arr_i = $arr_pri[$i] + 1;\n        $arr_k = $arr_pri[$k];\n        $stmt->execute();\n        while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) {\n            $ctmod[] = $r[\'ctmod\'];\n        }\n    }\n}\nelse{\n    die();\n}\n
Run Code Online (Sandbox Code Playgroud)\n

You*_*nse 5

我怀疑你在白名单方面确实有点过分了。不仅有白名单,还有准备好的声明。通过保护常量值,您过度设计了查询,使其难以阅读。

您需要了解任何恒定值在设计上都是安全的。因此,将其列入白名单或对其进行绑定绝对没有意义。按原样写就可以了。

所以,而不是

AND " . $field[3] . " = :m_act
Run Code Online (Sandbox Code Playgroud)

你应该写

AND versions.active = 'Y'
Run Code Online (Sandbox Code Playgroud)

没有任何绑定或白名单。

而仅应保护动态值。这意味着,在您的特定情况下,仅$arr_i$arr_k必须受到约束。所有其他查询部分都必须直接写入查询中,就像您之前所做的那样。

  • 我不知道你所说的“语气”是什么。我没有提到你的技能或知识或任何其他个人特征。我所做的只是回答你的问题,提供唯一可靠的答案。所以,请控制住你的想象力。 (5认同)
  • @YCS,这正是问题所在。我看到了你的干预。你经常这样做,却没有遭到拒绝,以至于你认为这样就可以了。嗯,事实并非如此。如果您愿意进一步讨论这个问题,我建议您通过我的个人资料电子邮件给我写信。我讨厌用这个来打扰其他人。 (3认同)