Les langages SQL Construire sa base, et s'y brancher
Interroger la base depuis un programme
Dans une application, le SQL n'est pas tapé à la main : il est fabriqué par un programme, à partir de ce que saisit l'utilisateur. C'est là que naissent la plupart des failles des sites web.
La faille
Un formulaire de recherche, en PHP :
// NE JAMAIS FAIRE
$sql = "SELECT * FROM clients WHERE prenom = '" . $_GET['prenom'] . "'";
Si quelqu'un saisit ' OR 1=1 --, la requête devient :
SELECT * FROM clients WHERE prenom = '' OR 1=1 --'
1=1 est vrai pour toutes les lignes, -- met la fin en commentaire : la
page affiche tous les clients. Appliqué à un UPDATE ou un DELETE,
le même principe modifie ou efface la base.
La cause : une valeur saisie a été collée dans le texte de la requête. La base ne distingue plus l'instruction de la donnée.
La réponse : la requête préparée
On envoie la requête et les valeurs séparément.
$requete = $pdo->prepare('SELECT * FROM clients WHERE prenom = :prenom');
$requete->execute(['prenom' => $_GET['prenom']]);
curseur.execute("SELECT * FROM clients WHERE prenom = ?", (prenom,))
const [lignes] = await connexion.execute('SELECT * FROM clients WHERE prenom = ?', [prenom]);
La valeur reste une valeur, quoi qu'elle contienne. Chaque langage a son écriture ; le principe est partout le même.
Ce qui ne marche pas
- Échapper soi-même les apostrophes : il reste toujours un cas oublié.
- Filtrer des mots (
DROP,OR) : cela bloque la cliente nommée Doris et laisse passer ce qui est écrit autrement. - Vérifier dans le navigateur : tout ce qui vient du navigateur peut être fabriqué.
Un ? remplace une valeur, jamais un nom de table ou de colonne : pour un
tri choisi par l'utilisateur, on compare son choix à une liste fermée de
colonnes autorisées.
Les autres réflexes
- Donner au compte de base de données de l'application le minimum de droits.
- Ne jamais afficher un message d'erreur SQL brut à l'utilisateur.
- Sauvegarder, et tester la restauration.