Une barre de recherche peut-elle voler une base ?
L'injection SQL est une attaque où un texte tapé dans un formulaire est pris pour une commande par la base de données. Elle existe depuis plus de vingt ans et elle marche encore, car une seule ligne de code oubliée suffit.
Aujourd'hui, tu comprends pourquoi, et tu apprends à la corriger.
À la fin de cette leçon
Remarque
Je peux écrire une requête SQL paramétrée qui ne peut pas être détournée.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Requête SQL | une demande écrite à une base de données | SELECT nom FROM eleves |
| Injection SQL | du texte tapé qui change le sens de la requête | |
| Concaténation | coller des morceaux de texte bout à bout | |
| Requête paramétrée | une requête où les valeurs arrivent à part | |
| Entrée | tout ce qu'un visiteur peut taper ou envoyer |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
La règle de ce lab
Important
Tu travailles seulement sur ta propre copie de la boutique du lab, avec la permission de ton enseignant. Ne teste jamais une injection sur un vrai site : même pour voir, c'est interdit sans accord. On apprend l'attaque pour écrire du code qui lui résiste.
Comment un texte devient une commande
Un site de lycée vérifie un nom avec une requête. Le code colle le texte tapé dans la requête, comme un morceau de phrase.
Si le texte contient des signes que SQL comprend, comme l'apostrophe, il sort de la place prévue et devient une partie de la commande. La base ne sait plus où finit la phrase du programmeur.
Exemple : la requête construite par concaténation
| Texte tapé | Requête reçue par la base | Effet |
|---|---|---|
| Camille | SELECT * FROM eleves WHERE nom = 'Camille' | Un seul élève |
| Camille' OR 1=1 -- | SELECT * FROM eleves WHERE nom = 'Camille' OR 1=1 --' | Tous les élèves : 1=1 est toujours vrai |
| L'Hopital | SELECT * FROM eleves WHERE nom = 'L'Hopital' | Une erreur : l'apostrophe coupe le texte |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une erreur fréquente
Attention
Beaucoup pensent qu'il suffit de retirer les apostrophes du texte tapé. Ce n'est pas assez : il existe d'autres astuces, et on casse les vrais noms comme L'Hopital. La bonne défense est de ne jamais coller le texte dans la requête.
Comment corriger : la requête paramétrée
Une requête paramétrée écrit la requête avec des places vides, notées ?. Les valeurs sont envoyées à part.
La base lit d'abord la requête, puis y met les valeurs comme de simples textes. Une apostrophe reste une apostrophe : elle ne peut plus devenir du code.
Exemple : chercher un nom avec un paramètre
import sqlite3
connexion = sqlite3.connect(":memory:")
connexion.execute("CREATE TABLE eleves (nom TEXT)")
connexion.execute("INSERT INTO eleves VALUES ('Camille')")
connexion.execute("INSERT INTO eleves VALUES ('Louis')")
# Le texte tapé arrive à part, à la place du point d'interrogation.
texte = "Camille' OR 1=1 --"
lignes = connexion.execute("SELECT nom FROM eleves WHERE nom = ?", (texte,)).fetchall()
print(lignes) # Change texte en "Louis" et relance.
Avant de commencer
Remarque
Appuie sur Start the lab et attends que la boutique soit prête. La boutique s'appelle Corner Shop : c'est le service app, sur le port 8000. Dans cette leçon, tu la regardes seulement. Le lab te demandera ensuite de la réparer.
Lis la page d'accueil de la boutique
curl -s http://app:8000/Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Fais une recherche normale : pen
curl -sG --data-urlencode "q=pen" http://app:8000/searchAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Fais une autre recherche normale : mug
curl -sG --data-urlencode "q=mug" http://app:8000/searchAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Demande une page inconnue, lis le code
curl -s -o /dev/null -w "%{http_code}\n" http://app:8000/inconnuAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Que montre une recherche normale ?
Une recherche normale renvoie les produits dont le nom contient le texte, un par ligne avec son prix. Le site n'a rien de suspect quand on s'en sert bien.
Le défaut est dans la façon dont le code construit la requête, pas dans ce qu'on voit. Dans le lab, tu cherches comment le code collerait le texte, puis tu le répares.
Pour aller plus loin : limiter les dégâts
Même bien écrit, un site peut avoir une autre faille. Une deuxième défense est de donner au site un compte de base de données qui ne peut lire que les tables dont il a besoin.
Pourquoi cela limite-t-il les dégâts si une injection passe quand même ? Réponds avec les mots table et droits.