L'idée est très simple: la requête et les données sont envoyées séparément au serveur de base de données .
C'est tout.
La racine du problème d'injection SQL réside dans le mélange du code et des données.
En fait, notre requête SQL est un programme légitime . Et nous créons un tel programme de manière dynamique, en ajoutant des données à la volée. Ainsi, les données peuvent interférer avec le code du programme et même le modifier, comme le montre chaque exemple d'injection SQL (tous les exemples en PHP / Mysql):
$expected_data = 1;
$query = "SELECT * FROM users where id=$expected_data";
produira une requête régulière
SELECT * FROM users where id=1
tandis que ce code
$spoiled_data = "1; DROP TABLE users;"
$query = "SELECT * FROM users where id=$spoiled_data";
produira une séquence malveillante
SELECT * FROM users where id=1; DROP TABLE users;
Cela fonctionne parce que nous ajoutons les données directement au corps du programme et qu'elles deviennent une partie du programme, de sorte que les données peuvent modifier le programme, et en fonction des données transmises, nous aurons soit une sortie régulière, soit une table users
supprimée.
Alors qu'en cas d'instructions préparées, nous ne modifions pas notre programme, il reste intact.
C'est le point.
Nous envoyons d'abord un programme au serveur
$db->prepare("SELECT * FROM users where id=?");
où les données sont remplacées par une variable appelée paramètre ou espace réservé.
Notez qu'exactement la même requête est envoyée au serveur, sans aucune donnée! Et puis nous envoyons les données avec la deuxième requête, essentiellement séparée de la requête elle-même:
$db->execute($data);
il ne peut donc pas modifier notre programme et faire du mal.
Assez simple - n'est-ce pas?
La seule chose que je dois ajouter qui est toujours omise dans chaque manuel:
Les instructions préparées ne peuvent protéger que les littéraux de données , mais ne peuvent être utilisées avec aucune autre partie de requête.
Donc, une fois que nous devons ajouter, disons, un identifiant dynamique - un nom de champ, par exemple - les instructions préparées ne peuvent pas nous aider. J'ai expliqué la question récemment , donc je ne me répéterai pas.