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 ?

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 ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2025-01-23 18:08:10369parcourir

How Can We Securely Use Parameterized Table Names in Prepared Statements to Prevent SQL Injection?

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn