Aller au contenu

TP – Enregistrer les réservations en base

BTS SIO SISR 2e année – Bloc 1 – S09 – binôme

Note

But. Tu crées la base du portail, tu l'interroges, tu écris deux pages PHP (liste et ajout) avec des requêtes préparées, tu réalises une injection SQL sur une page volontairement vulnérable puis tu la corriges, et tu limites les droits du compte.

Durée : 2 h 50 (parties A à D), plus le bilan. Prérequis : cours S09 lu ; S07 et S08. Fichiers : schema.sql, connexion.php, injection-vulnerable.php.

Note

Comment ce TP fonctionne. Avant chaque manipulation, tu écris ce que tu anticipes (« J'anticipe »). Puis tu confrontes avec les éléments de réponse.

Binôme : ____________ / ____________

Contraintes

  • Travail uniquement sur la machine virtuelle de laboratoire (Debian ou Ubuntu avec Apache, PHP, extension PDO MySQL et MariaDB). Le mot de passe du compte portail est un identifiant de laboratoire.
  • La page vulnérable ne sert que pour la démonstration ; elle n'est jamais installée sur un serveur accessible de l'extérieur.
  • Les associations, adresses et dates sont fictives.

Partie A – Créer et interroger la base (≈ 40 min)

  1. Charge le schéma : sudo mariadb < schema.sql.
  2. Crée un compte à droits limités :
CREATE USER 'portail'@'localhost' IDENTIFIED BY 'motdepasse-de-labo';
GRANT SELECT, INSERT ON portail.* TO 'portail'@'localhost';
FLUSH PRIVILEGES;
  1. Écris et exécute les requêtes suivantes :
N° Besoin Ta requête
1 Les salles de 50 places ou plus, de la plus grande à la plus petite
2 Le nombre de réservations par salle le 15 mars 2030
3 Le nombre de minutes réservées par salle (toutes dates)
4 Le créneau 10 h–12 h de la salle 1 le 15 mars 2030 est-il libre ?

J'anticipe. Que renvoie la requête 4 ? Et pour 11 h–12 h ? ______________________

Éléments de réponse
  1. SELECT nom, capacite FROM salles WHERE capacite >= 50 ORDER BY capacite DESC; → salle des fêtes (200), gymnase (120), salle d'exposition (60).
  2. SELECT s.nom, COUNT(*) FROM reservations r JOIN salles s ON s.id = r.salle_id WHERE r.jour = '2030-03-15' GROUP BY s.nom; → salle des fêtes 2, salle du conseil 1.
  3. SELECT s.nom, SUM(TIME_TO_SEC(r.fin) - TIME_TO_SEC(r.debut)) / 60 FROM reservations r JOIN salles s ON s.id = r.salle_id GROUP BY s.nom; → gymnase 120, salle des fêtes 210, salle du conseil 120.
  4. SELECT COUNT(*) FROM reservations WHERE salle_id = 1 AND jour = '2030-03-15' AND debut < '12:00' AND fin > '10:00'; → 1 (la réservation 9 h–11 h gêne : créneau non libre). Pour 11 h–12 h : debut < '12:00' AND fin > '11:00' → 0 : libre.

Partie B – Les pages PHP (≈ 55 min)

  1. Place connexion.php à côté de tes pages. Écris reservations.php : affiche, dans un tableau HTML, les réservations d'un jour (paramètre jour, par défaut le 15 mars 2030) avec le nom de la salle, l'association et les heures. Requête préparée ; affichage avec htmlspecialchars.
  2. Écris reserver.php : reçoit le formulaire de S06 (méthode POST), refait les contrôles (nom, courriel valide, salle, format de date et d'heures, fin après début), refuse un chevauchement (code 409) et sinon insère la réservation (requête préparée).

Tests. Complète :

Demande Code attendu Résultat obtenu
Salle 1, 15 mars 2030, 10:00 → 12:00
Salle 1, 15 mars 2030, 11:00 → 12:00
Nom vide, courriel « x », fin avant début

Je comprends. Pourquoi reserver.php refait-il les contrôles déjà faits par salles.js (S07) ? ______________________

Éléments de réponse

Tests : 10 h–12 h → 409 (« Ce créneau est déjà réservé ») ; 11 h–12 h → 200 (« Réservation enregistrée ») ; saisie invalide → 400 (« Demande invalide »). Le navigateur est sous le contrôle de l'utilisateur : il peut contourner salles.js ou envoyer une requête sans la page. Le serveur ne peut faire confiance qu'à lui-même.

Partie C – L'injection SQL (≈ 40 min)

  1. Installe injection-vulnerable.php (laboratoire uniquement). Appelle-la avec ?association=Chorale : une ligne.
  2. Appelle-la avec ?association=x' OR '1'='1 (adresse encodée par le navigateur). Que se passe-t-il ? ______________________
  3. Explique pourquoi à partir de la requête finale construite : ______________________
  4. Corrige la page avec une requête préparée et rejoue la même saisie : résultat ? ______________________
  5. Avec le compte portail, essaie DELETE FROM reservations; puis un INSERT avec une fin avant le début : que répond la base ? ______________________
Éléments de réponse
  1. Toutes les réservations s'affichent, avec les courriels de tout le monde : fuite de données personnelles. 3. La requête devient … WHERE association = 'x' OR '1'='1' : la condition '1'='1' est toujours vraie. 4. Avec prepare et execute([$association]), la saisie est traitée comme un texte : aucune ligne ne correspond. 5. ERROR 1142 : DELETE command denied (moindre privilège) et ERROR 4025 : CONSTRAINT failed (contrainte CHECK (fin > debut)) : la base protège aussi quand le code se trompe.

Partie D – Bilan de sécurité (≈ 25 min, individuel)

Rédige une fiche de revue d'une page : cinq points à vérifier dans une page PHP qui accède à la base (par exemple : requêtes préparées, contrôle serveur, échappement de l'affichage, droits du compte, erreurs non affichées) et, pour chacun, comment tu le vérifies.

Retour en entreprise (si ta situation le permet)

Demande à ton tuteur comment est géré l'accès à la base d'une application de l'entreprise : quel compte, quels droits, où est stocké le mot de passe ? Ne note aucun identifiant réel ; décris seulement la pratique.

Rendu

Archive RENDU-B1A2-S09-NOM.zip : requêtes de la partie A avec résultats, reservations.php, reserver.php, version corrigée de la page vulnérable, réponses de la partie C et fiche de revue (D). Aucun identifiant réel.

Bilan de la séance

Remplis ce bilan seul, honnêtement : il sert à décider ce qu'il faut reprendre. Niveau : Non maîtrisé, Maîtrise partielle, Bonne maîtrise ou Excellente maîtrise (le vocabulaire des grilles nationales d'évaluation), ou Non évalué.

Compétence du référentiel Ce que j'ai fait dans cette séance Niveau
B1.3 – Développer la présence en ligne de l'organisation
B1.5 – Mettre à disposition des utilisateurs un service informatique

Note

Les codes sont ceux du référentiel.

Je sais faire, sans aide :

  • Écrire des requêtes SELECT, JOIN et GROUP BY
  • Utiliser des requêtes préparées
  • Reproduire et corriger une injection SQL
  • Appliquer le moindre privilège et le contrôle serveur

Ce que je dois reprendre : ______________________

Ma question à poser à l'enseignant : ______________________