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}\nRun Code Online (Sandbox Code Playgroud)\n
我怀疑你在白名单方面确实有点过分了。不仅有白名单,还有准备好的声明。通过保护常量值,您过度设计了查询,使其难以阅读。
您需要了解任何恒定值在设计上都是安全的。因此,将其列入白名单或对其进行绑定绝对没有意义。按原样写就可以了。
所以,而不是
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必须受到约束。所有其他查询部分都必须直接写入查询中,就像您之前所做的那样。