Maison >base de données >tutoriel mysql >Comment pouvons-nous utiliser en toute sécurité les noms de tables paramétrés dans les instructions préparées pour empêcher l'injection SQL ?
Noms de tables paramétrés dans les instructions préparées : un dilemme
Bien que mysqli_stmt_bind_param se soit révélé efficace pour se protéger contre l'injection SQL, il rencontre des limites lorsque les variables affectant les noms de tables sont impliqués. Comme illustré dans l'extrait de code fourni :
function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ) { $statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }
La concaténation problématique de $new_table introduit une vulnérabilité à l'injection SQL. Les tentatives pour remplacer ceci par un autre espace réservé, comme le montre l'extrait suivant, échouent :
function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ) { $statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }
Les limites des déclarations préparées
Le problème principal réside dans l'incapacité d'instructions préparées pour protéger les paramètres qui définissent la structure de l'instruction SQL, tels que les noms de tables. En effet, les instructions préparées autorisent exclusivement des paramètres pour des valeurs qui ne modifient pas la signification de l'instruction. Étant donné que les noms de table déterminent la validité de l'instruction SQL, les modifier pendant l'exécution pourrait potentiellement l'invalider.
Même avec des interfaces de base de données comme PDO qui émulent les instructions préparées en substituant des paramètres avant de les envoyer à la base de données, les valeurs d'espace réservé sont toujours chaînes incluses dans l’instruction SQL. En conséquence, SELECT FROM ? avec mytable comme paramètre enverrait finalement SELECT FROM 'mytable' à la base de données, le rendant invalide.
Atténuer le risque
L'approche la plus sécurisée reste en utilisant $mytable dans une chaîne, mais il doit être accompagné d'une liste blanche de tables par rapport auxquelles l'entrée de l'utilisateur est vérifiée. Cela empêche les acteurs malveillants d'exécuter des instructions SQL sur des tables arbitraires. Par conséquent, le code suivant démontre une implémentation sécurisée :
if (whitelisted_tables($mytable)) { $statement = $mysqli->prepare("INSERT INTO $mytable VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!