Il y a en fait deux questions en une. Et la question du titre a très peu à voir avec les préoccupations exprimées par le PO dans les commentaires qui suivent.
Bien que je réalise que pour l'OP, c'est leur cas particulier qui compte, pour les lecteurs venant de Google, il est important de répondre à la question plus générale, qui peut être formulée comme "est la concaténation aussi sûre que les déclarations préparées si je me suis assuré que chaque littéral que je concatène est sûr? ". Alors, je voudrais me concentrer sur ce dernier. Et la réponse est
Définitivement non.
L'explication n'est pas aussi directe que la plupart des lecteurs le souhaiteraient, mais je ferai de mon mieux.
Je réfléchis à la question depuis un moment, ce qui a abouti à l' article (bien que basé sur l'environnement PHP) où j'ai essayé de tout résumer. Il m'est venu à l'esprit que la question de la protection contre l'injection SQL échappe souvent à certains sujets connexes mais plus étroits, comme l'échappement de chaîne, la conversion de type, etc. Bien que certaines des mesures puissent être considérées comme sûres lorsqu'elles sont prises par elles-mêmes, il n'y a pas de système, ni de règle simple à suivre. Ce qui rend le terrain très glissant, mettant trop l'accent sur l'attention et l'expérience du développeur.
La question de l'injection SQL ne peut pas être simplifiée à une question de syntaxe particulière. C'est plus large que la moyenne des développeurs de penser. C'est aussi une question méthodologique . Il ne s'agit pas seulement de «quelle mise en forme particulière nous devons appliquer», mais aussi de « comment cela doit être fait».
(De ce point de vue, un article de Jon Skeet cité dans l'autre réponse fait plutôt mal que bien, car il est à nouveau pinailleur sur un cas particulier, se concentrant sur un problème de syntaxe particulier et ne parvenant pas à résoudre le problème dans son ensemble.)
Lorsque vous essayez d'aborder la question de la protection non pas dans son ensemble mais comme un ensemble de problèmes de syntaxe différents, vous êtes confronté à une multitude de problèmes.
- la liste des choix de formatage possibles est vraiment énorme. Cela signifie que l'on peut facilement en oublier. Ou confondez-les (en utilisant une chaîne d' échappement pour l' identifiant par exemple).
- La concaténation signifie que toutes les mesures de protection doivent être effectuées par le programmeur et non par le programme. Ce problème à lui seul entraîne plusieurs conséquences:
- un tel formatage est manuel. Manuel signifie extrêmement sujet aux erreurs. On pourrait simplement oublier de postuler.
- de plus, il y a une tentation de déplacer les procédures de formatage dans une fonction centralisée, ce qui dérange encore plus les choses et gâche les données qui ne vont pas dans la base de données.
- lorsque plus d'un développeur est impliqué, les problèmes se multiplient par dix.
- lorsque la concaténation est utilisée, on ne peut pas dire en un coup d'œil une requête potentiellement dangereuse: elles sont toutes potentiellement dangereuses!
Contrairement à ce désordre, les déclarations préparées sont en effet le Saint Graal:
- il peut être exprimé sous la forme d'une règle simple et facile à suivre.
- il s'agit essentiellement d'une mesure indétachable, ce qui signifie que le développeur ne peut pas interférer et, volontairement ou non, gâcher le processus.
- la protection contre l'injection n'est en réalité qu'un effet secondaire des instructions préparées, dont le but réel est de produire une instruction syntaxiquement correcte. Et une déclaration syntaxiquement correcte est 100% preuve d'injection. Pourtant, nous avons besoin que notre syntaxe soit correcte malgré toute possibilité d'injection.
- s'il est utilisé sur tout le pourtour, il protège l'application quelle que soit l'expérience du développeur. Dites, il y a une chose appelée injection de second ordre . Et une très forte illusion qui se lit "afin de protéger, évitez toutes les entrées fournies par l'utilisateur ". Combinées ensemble, elles conduisent à l'injection, si un développeur prend la liberté de décider, ce qui doit être protégé et ce qui ne l'est pas.
(En réfléchissant plus loin, j'ai découvert que l'ensemble actuel d'espaces réservés n'est pas suffisant pour les besoins réels et doit être étendu, à la fois pour les structures de données complexes, comme les tableaux, et même les mots-clés ou identifiants SQL, qui doivent parfois être ajoutés au requête dynamiquement aussi, mais un développeur n'est pas armé pour un tel cas, et obligé de revenir à la concaténation de chaînes, mais c'est une autre question).
Fait intéressant, la controverse de cette question est provoquée par la nature très controversée de Stack Overflow. L'idée du site est d'utiliser des questions particulières d'utilisateurs qui les demandent directement pour atteindre l'objectif d'avoir une base de données de réponses à usage général adaptée aux utilisateurs issus de la recherche . L'idée n'est pas mauvaise en soi , mais elle échoue dans une situation comme celle-ci: lorsqu'un utilisateur pose une question très étroite , notamment pour obtenir une dispute dans un différend avec un collègue (ou pour décider s'il vaut la peine de refactoriser le code). Alors que la plupart des participants expérimentés essaient d'écrire une réponse, en gardant à l'esprit la mission de Stack Overflow dans son ensemble, ce qui rend leur réponse bonne pour autant de lecteurs que possible, pas seulement pour l'OP.