Une injection SQL survient dès qu'une donnée non fiable est concaténée dans le texte d'une requête. L'attaquant fournit une valeur qui referme la chaîne et détourne la logique. Reproduisons l'attaque sur une table users : concaténer directement l'entrée ada' OR '1'='1 transforme un filtre précis en condition toujours vraie.
SQL
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
is_admin INTEGER NOT NULL DEFAULT 0
);
INSERT INTO users (id, name, is_admin)
VALUES (1, 'ada', 0), (2, 'root', 1);
-- Concatenation dangereuse (ne JAMAIS faire)
-- entree = ada' OR '1'='1
SELECT * FROM users
WHERE name = 'ada' OR '1'='1';
La requête injectée renvoie TOUTES les lignes.
Le payload fonctionne parce que le guillemet ferme prématurément le littéral 'ada', puis OR '1'='1' ajoute une condition universellement vraie. Une variante ajoute -- pour commenter la fin de la requête d'origine. La leçon : tant que la donnée et le code partagent la même chaîne, aucun échappement manuel n'est vraiment fiable.
SQL
-- Placeholder positionnel
SELECT * FROM users WHERE name = ?;
-- Placeholder nomme
SELECT * FROM users WHERE name = :name;
Deux formes de paramètres liés en SQLite.
La parade est la requête préparée : le pilote compile d'abord la structure de la requête, puis lie les valeurs séparément. La donnée liée n'est jamais analysée comme du SQL, seulement comparée. En prime, la structure compilée est réutilisable : lier successivement plusieurs valeurs évite de recompiler le plan à chaque appel.
SQL
-- La valeur liee reste une donnee, pas du SQL
SELECT * FROM users
WHERE name = :name;
-- :name = ada' OR '1'='1
-- -> 0 ligne : aucun utilisateur ne
-- porte ce nom litteral
Le même payload, désormais inoffensif.
Quiz de validation
Vérifiez que vous avez bien retenu les points clés de cette leçon.
Pourquoi une requête préparée avec paramètres empêche-t-elle l'injection SQL ?
Parce qu'elle chiffre les valeurs transmises
Parce que la valeur liée est traitée comme une donnée, jamais analysée comme du SQL
Parce qu'elle échappe automatiquement les guillemets dans la chaîne
Parce qu'elle limite la longueur des entrées utilisateur
Le payload ' OR '1'='1 réussit une injection parce qu'il...
sature la mémoire du serveur de base de données
ferme le littéral de chaîne puis ajoute une condition toujours vraie
supprime la table ciblée par la requête
modifie les droits de l'utilisateur courant
Peut-on lier un nom de table via un paramètre ? ?
Oui, les placeholders acceptent tout type d'identifiant
Non : les placeholders ne lient que des valeurs ; un identifiant doit être validé contre une liste blanche