83 votes

Puis-je paramétrer le nom de la table dans une instruction préparée ?

J'ai utilisé la fonction mysqli_stmt_bind_param à plusieurs reprises. Cependant, si je sépare les variables que j'essaie de protéger contre l'injection SQL, je rencontre des erreurs.

Voici un exemple de code :

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();
}

Est-il possible de remplacer d'une manière ou d'une autre le .$new_table. concaténation avec une autre instruction de point d'interrogation, créer une autre instruction de paramètre de liaison, ou ajouter à l'instruction existante pour se protéger contre l'injection SQL ?

Comme ceci ou une forme de ceci :

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();
}

101voto

Sam Graham Points 394

La réponse courte à votre question est "non".

Au sens strict, au niveau de la base de données, les instructions préparées permettent uniquement de lier des paramètres aux "valeurs" de l'instruction SQL.

Une façon de voir les choses est de dire "ce qui peut être remplacé lors de l'exécution de la déclaration sans en modifier le sens". Le(s) nom(s) de table n'est (ne sont) pas une de ces valeurs d'exécution, car il(s) détermine(nt) la validité de l'instruction SQL elle-même (c'est-à-dire quels noms de colonnes sont valides) et le fait de le(s) changer au moment de l'exécution pourrait potentiellement modifier la validité de l'instruction SQL.

À un niveau légèrement supérieur, même dans les interfaces de base de données qui émulent la substitution des paramètres des instructions préparées plutôt que d'envoyer réellement des instructions préparées à la base de données, comme PDO, qui pourrait vous permettre d'utiliser un espace réservé n'importe où (puisque l'espace réservé est remplacé avant d'être envoyé à la base de données dans ces systèmes), la valeur de l'espace réservé de la table serait une chaîne, et incluse en tant que telle dans le code SQL envoyé à la base de données, de sorte que SELECT * FROM ? con mytable car le param finirait par envoyer SELECT * FROM 'mytable' à la base de données, ce qui est un code SQL non valide.

Le mieux est de continuer avec

SELECT * FROM {$mytable}

mais vous absolument devrait disposer d'une liste blanche de tables que vous vérifiez en premier lieu si cette $mytable provient de l'entrée de l'utilisateur.

1voto

Fred -ii- Points 23477

La même règle s'applique à la création d'une "base de données".

Vous ne pouvez pas utiliser une instruction préparée pour lier une base de données.

C'est-à-dire :

CREATE DATABASE IF NOT EXISTS ?

ne fonctionnera pas. Utilisez plutôt une liste de sécurité.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X