Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 1322 minIntermédiaire

Épreuve blanche E7 n° 2 : une coopérative agricole et sa boutique en ligne

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • traiter un sujet complet de type 2026 en 4 heures ;
  • corriger du code PHP et des droits MySQL comme le jour de l'épreuve ;
  • vérifier ta gestion du temps sur deux gros dossiers.

2 exercices corrigés

Cette seconde épreuve blanche d'E7 SLAM suit le modèle du sujet 2026 (cas NDV) : deux dossiers de 40 points, un intranet à faire évoluer puis un site repris d'un autre prestataire, beaucoup de code PHP et de SQL à corriger. Elle complète la première, plus orientée analyse de risques. Passe-la en 4 heures, sans document, et rédige chaque réponse avant d'ouvrir sa correction. Les corrections sont des propositions détaillées, pas un corrigé officiel.

Comment l'utiliser

Même règle que pour l'épreuve blanche n° 1 : 20 minutes de lecture et de plan, puis environ 1 h 40 à 1 h 45 par dossier (1 h 40 pour l'un, 1 h 45 pour l'autre) et 15 minutes de relecture. Les deux dossiers sont indépendants. Si tu bloques sur le dossier A, passe au B à l'heure prévue.

Présentation du contexte

Vertalis est une coopérative qui regroupe 240 exploitations agricoles en agriculture biologique. Elle collecte leurs productions, les revend à des magasins et à des particuliers, et verse chaque mois aux adhérents le paiement de leurs livraisons. Ses salariés utilisent VertaNet, un intranet développé en PHP avec une base MySQL 8.4 nommée vertanet. Depuis trois ans, la coopérative vend aussi des paniers de légumes en ligne sur Panier Vertalis, un site développé par un ancien prestataire.

Vertalis a confié la maintenance de ses deux applications à l'entreprise de services du numérique Kodex. Tu es stagiaire dans le pôle « Audit et sécurité » de Kodex. Ta tutrice, Mme Rinaldi, te confie deux missions.

DossierThèmePoints
AÉvolutions de l'intranet VertaNet en matière de sécurité40
BReprise et sécurisation de la boutique Panier Vertalis40
Total80

Dossier A : évolutions de l'intranet VertaNet en matière de sécurité (40 points)

Mission A1 – Exploiter les journaux du SGBD. Les opérations sur la base vertanet sont journalisées dans une vue v_journal (log_date, log_nature, log_user, log_host, log_contenu), alimentée par le journal général de MySQL. Une page de VertaNet permet de les consulter, filtrées par date. Mme Rinaldi souhaite pouvoir aussi filtrer par compte MySQL, choisi dans une liste déroulante nommée compte.

Document A1 : extrait de journal.php

php
1.  function afficherJournal(PDO $pdo): array {
2.      $conditions = [];
3.      $parametres = [];
4.      if (!empty($_POST['date'])) {
5.          $conditions[] = 'DATE(log_date) = :date';
6.          $parametres[':date'] = $_POST['date'];
7.      }
8.      // ** filtre par compte à ajouter **
9.      $sql = 'SELECT log_date, log_nature, log_user, log_host, log_contenu FROM v_journal';
10.     if (count($conditions) > 0) {
11.         $sql .= ' WHERE ' . implode(' AND ', $conditions);
12.     }
13.     $sql .= ' ORDER BY log_date';
14.     $stmt = $pdo->prepare($sql);
15.     $stmt->execute($parametres);
16.     return $stmt->fetchAll(PDO::FETCH_ASSOC);
17. }

Document A2 : extrait de connexion_bdd.php

php
1. function connexionBdd(): PDO {
2.     $dsn = 'mysql:dbname=vertanet;host=localhost;charset=utf8mb4';
3.     return new PDO($dsn, 'vertanet_web', 'Vt!2024web');
4. }

Le compte vertanet_web est celui qu'utilise VertaNet, hébergé sur le même serveur que la base. Il ne devrait pouvoir se connecter que depuis ce serveur et ne devrait que lire, ajouter, modifier et supprimer des lignes dans les tables de la base vertanet.

Document A3 : extrait du journal du 8 avril 2027

text
2027-04-08 23:12:40 [CONNEXION]   [vertanet_web]@[203.0.113.45] Connect vertanet_web@203.0.113.45 on vertanet
2027-04-08 23:13:02 [REQUETE]     [vertanet_web]@[203.0.113.45] SELECT user, host, authentication_string FROM mysql.user
2027-04-08 23:14:15 [REQUETE]     [vertanet_web]@[203.0.113.45] DROP TABLE Paiement_2025
2027-04-08 23:14:16 [DECONNEXION] [vertanet_web]@[203.0.113.45] Quit

Document A4 : habilitations actuelles (résultat de SHOW GRANTS)

text
GRANT ALL PRIVILEGES ON *.* TO `vertanet_web`@`%`

Mission A2 – Protéger les coordonnées bancaires des adhérents. La table Adherent (id, siret, raisonSociale, nomGerant, prenomGerant, telephone, mel, iban, surfaceHa, certificationBio) stocke l'IBAN en clair, en VARCHAR(34). La plupart des adhérents sont des exploitants individuels. Mme Rinaldi demande de chiffrer les IBAN existants avec AES_ENCRYPT(), dans une colonne VARBINARY(64), avec la clé Vrt#2027!k9. Dans l'application, cette clé sera lue dans la variable d'environnement $_ENV['AES_KEY'].

Document A5 : méthode getCoordonneesBancaires

php
1. public function getCoordonneesBancaires(int $idAdherent): array {
2.     $sql = "SELECT raisonSociale, iban FROM Adherent WHERE id = :id";
3.     $stmt = $this->db->prepare($sql);
4.     $stmt->bindValue(':id', $idAdherent, PDO::PARAM_INT);
5.     $stmt->execute();
6.     return $stmt->fetch(PDO::FETCH_ASSOC);
7. }

Mission A3 – Gérer des délégations temporaires. Les droits des salariés dans VertaNet sont stockés dans Habilitation (idCompte, idFonctionnalite), avec Compte (id, login) et Fonctionnalite (id, libelle). Ces droits sont permanents. Pendant les congés, la responsable financière veut déléguer à un collègue certaines fonctionnalités (« Valider un paiement »), pour une période précise, sans toucher à ses droits permanents. On doit savoir qui a accordé chaque délégation et en garder l'historique, y compris après leur expiration.

Exercice 1 sur 2 Dossier A : les questions Réussi À revoir

  • A1.1 Compléter la fonction afficherJournal() pour filtrer aussi par compte. Indiquer seulement les lignes ajoutées ou modifiées, avec leurs numéros.
  • A1.2 a) Indiquer les éléments du journal (document A3) qui montrent que le compte vertanet_web se connecte depuis une autre machine que le serveur local et dispose de plus de droits que nécessaire. b) Indiquer les éléments des habilitations (document A4) qui le permettent. c) Écrire les requêtes qui donnent au compte exactement les droits nécessaires.
  • A1.3 Relever, dans le document A2, une autre faiblesse qui a pu faciliter l'intrusion, et proposer une correction.
  • A2.1 Indiquer si l'IBAN d'un adhérent est une donnée à caractère personnel, puis lister les autres données à caractère personnel de la table Adherent.
  • A2.2 Écrire les requêtes qui adaptent la table et chiffrent les IBAN existants.
  • A2.3 Corriger la méthode getCoordonneesBancaires() pour qu'elle renvoie l'IBAN en clair.
  • A2.4 Un collègue propose de hacher les IBAN avec password_hash() « parce que c'est plus sûr ». Lui répondre.
  • A3.1 Proposer les modifications du schéma de la base pour gérer les délégations temporaires, dans le formalisme de ton choix.
  • A3.2 Écrire la requête qui liste les libellés des fonctionnalités que le compte d'identifiant 2 peut utiliser aujourd'hui, droits permanents et délégations en cours compris, sans doublon.
Voir la réponseMasquer la réponse de l'exercice 1

A1.1. La ligne 8 est remplacée par :

php
8.  if (!empty($_POST['compte'])) {
8a.     $conditions[] = 'log_user = :compte';
8b.     $parametres[':compte'] = $_POST['compte'];
8c. }

Le compte est transmis comme valeur liée, jamais concaténé dans la requête : la liste déroulante peut être modifiée par l'utilisateur, la requête préparée le neutralise.

A1.2 a) Journal. Le compte se connecte depuis l'adresse 203.0.113.45 (ligne de 23:12:40), qui n'est pas le serveur local (localhost, 127.0.0.1). Il lit la table système mysql.user (23:13:02), qui contient les comptes et les empreintes de leurs mots de passe, et il supprime une table (DROP TABLE Paiement_2025, 23:14:15) : deux opérations qui dépassent la lecture et la modification de lignes.

A1.2 b) Habilitations. L'hôte % autorise la connexion depuis n'importe quelle adresse. ALL PRIVILEGES ON *.* donne tous les privilèges sur toutes les bases du serveur, y compris la base système mysql, DROP et la création de comptes.

A1.2 c) Requêtes.

sql
RENAME USER 'vertanet_web'@'%' TO 'vertanet_web'@'localhost';
REVOKE ALL PRIVILEGES ON *.* FROM 'vertanet_web'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON vertanet.* TO 'vertanet_web'@'localhost';
ALTER USER 'vertanet_web'@'localhost' IDENTIFIED BY 'nouveau_mot_de_passe_long_et_aleatoire';

Le REVOKE vise le niveau global *.*, celui où les privilèges ont été accordés. Le changement de mot de passe s'impose : l'attaquant le connaît. Il faut ensuite mettre à jour la configuration de VertaNet et restaurer la table supprimée depuis la dernière sauvegarde.

A1.3. Le mot de passe du compte est écrit en clair dans le code source (ligne 3). Il est lisible par toute personne qui accède au code : dépôt Git, poste d'un développeur, sauvegarde, ancien prestataire. Correction : le placer dans une variable d'environnement ou un fichier de configuration hors de la racine Web et exclu du dépôt, lu par getenv() ou $_ENV ; changer le mot de passe, puisqu'il a pu circuler. C'est une mauvaise configuration de sécurité (A05:2021).

A2.1. Oui. La plupart des adhérents sont des exploitants individuels : l'IBAN de leur compte se rapporte à une personne physique identifiée. C'est une donnée à caractère personnel, et une donnée financière à protéger particulièrement, même si elle ne fait pas partie des données sensibles de l'article 9 du RGPD. Autres données personnelles : nomGerant, prenomGerant, telephone, mel ; le siret, la raisonSociale, la surfaceHa et la certificationBio d'une exploitation individuelle permettent aussi d'identifier l'exploitant, donc le deviennent indirectement.

A2.2.

sql
ALTER TABLE Adherent MODIFY iban VARBINARY(64);
UPDATE Adherent SET iban = AES_ENCRYPT(iban, 'Vrt#2027!k9');

A2.3. Ligne 2 modifiée et une ligne ajoutée :

php
2.  $sql = "SELECT raisonSociale, CAST(AES_DECRYPT(iban, :cle) AS CHAR) AS iban
            FROM Adherent WHERE id = :id";
4a. $stmt->bindValue(':cle', $_ENV['AES_KEY'], PDO::PARAM_STR);

L'alias AS iban conserve la clé de tableau attendue par le code appelant. La clé de chiffrement est passée en paramètre, jamais écrite dans le code.

A2.4. Le hachage est irréversible : une fois haché, l'IBAN ne pourrait plus jamais être relu, alors que la coopérative en a besoin chaque mois pour verser les paiements. password_hash() convient aux mots de passe, qu'on vérifie sans les relire. Pour une donnée qu'il faut retrouver en clair, la bonne mesure est le chiffrement, avec une clé protégée et distincte de la base.

A3.1. Une proposition, en schéma relationnel :

text
Delegation (id, idCompte, idFonctionnalite, idDelegant, dateDebut, dateFin)
    clé primaire : id
    idCompte : clé étrangère en référence à id de Compte (bénéficiaire)
    idFonctionnalite : clé étrangère en référence à id de Fonctionnalite
    idDelegant : clé étrangère en référence à id de Compte (qui accorde)

La table Habilitation n'est pas modifiée : les droits permanents restent séparés. Chaque délégation est une ligne datée qui n'est jamais supprimée à son expiration : l'historique est conservé. Une clé primaire technique (id) permet d'accorder plusieurs fois la même délégation à des périodes différentes. Contrôles à prévoir : dateFin >= dateDebut (contrainte CHECK), et le délégant doit lui-même posséder la fonctionnalité qu'il délègue (déclencheur ou contrôle applicatif).

A3.2.

sql
SELECT f.libelle
FROM Habilitation h
JOIN Fonctionnalite f ON f.id = h.idFonctionnalite
WHERE h.idCompte = 2
UNION
SELECT f.libelle
FROM Delegation d
JOIN Fonctionnalite f ON f.id = d.idFonctionnalite
WHERE d.idCompte = 2
  AND CURDATE() BETWEEN d.dateDebut AND d.dateFin;

UNION supprime les doublons : si une délégation porte sur une fonctionnalité que le compte possède déjà, elle n'apparaît qu'une fois. UNION ALL la montrerait deux fois. Exemple : un compte qui possède en permanence « Consulter les adhérents » et « Saisir une collecte », avec une délégation en cours sur « Valider un paiement », une autre en cours sur « Consulter les adhérents » et une délégation expirée sur « Modifier un IBAN », obtient trois libellés : les deux permanents et « Valider un paiement ».

Tu avais trouvé ?

Dossier B : reprise et sécurisation de la boutique Panier Vertalis (40 points)

Avant de reprendre la maintenance de Panier Vertalis, Kodex en audite le code. Plusieurs clients ont signalé des comportements anormaux : un avis produit qui ouvre une fenêtre publicitaire, une adresse électronique de compte modifiée sans action de leur part, une facture d'un autre client affichée à l'écran.

Mission B1 – Les avis des clients. Chaque produit affiche les avis laissés par les clients connectés.

Document B1 : affichage des avis (avis.php, extrait)

php
1. $stmt = $pdo->prepare("SELECT pseudo, note, texte FROM Avis WHERE idProduit = :id");
2. $stmt->execute([':id' => $idProduit]);
3. foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $avis) {
4.     echo '<div class="avis"><strong>' . $avis['pseudo'] . '</strong> ';
5.     echo $avis['note'] . '/5<p>' . $avis['texte'] . '</p></div>';
6. }

Un avis enregistré contient : Très bons légumes <script>window.location='https://promo-legumes.example'</script>.

Mission B2 – La modification de l'adresse électronique.

Document B2 : formulaire (mon_compte.php, extrait) et traitement (traiter_mel.php)

php
// mon_compte.php
1. <form method="post" action="traiter_mel.php">
2.     <input type="email" name="mel" required>
3.     <button type="submit">Enregistrer</button>
4. </form>
php
// traiter_mel.php
1. session_start();
2. if (!isset($_SESSION['idClient'])) { header('Location: connexion.php'); exit; }
3. $stmt = $pdo->prepare("UPDATE Client SET mel = :mel WHERE id = :id");
4. $stmt->execute([':mel' => $_POST['mel'], ':id' => $_SESSION['idClient']]);
5. header('Location: mon_compte.php?maj=ok');

La page mon_compte.php commence par session_start(). La réinitialisation du mot de passe envoie un lien à l'adresse électronique du compte.

Mission B3 – Les mots de passe. La colonne Client.mdp contient des empreintes de 32 caractères hexadécimaux, calculées par md5($mdp). Mme Rinaldi veut passer à password_hash() sans obliger tous les clients à réinitialiser leur mot de passe : chaque empreinte doit être remplacée lors de la prochaine connexion réussie du client.

Mission B4 – Les factures.

Document B3 : facture.php (extrait), appelée par facture.php?num=F2027-00418

php
1. session_start();
2. $num = $_GET['num'];
3. $stmt = $pdo->prepare("SELECT numero, dateFacture, montantTTC, adresseLivraison
4.                        FROM Facture WHERE numero = ?");
5. $stmt->execute([$num]);
6. $facture = $stmt->fetch(PDO::FETCH_ASSOC);

La table Facture contient une colonne idClient. Les numéros de facture se suivent.

Exercice 2 sur 2 Dossier B : les questions Réussi À revoir

  • B1.1 Nommer l'attaque subie par les visiteurs de la page des avis et la situer dans l'OWASP Top 10 2021. Expliquer pourquoi elle touche plus de visiteurs que la même attaque placée dans un lien.
  • B1.2 Modifier le code du document B1 pour empêcher l'exécution du script. Indiquer les lignes modifiées.
  • B1.3 Expliquer pourquoi la protection doit se faire à l'affichage, même si les saisies sont aussi contrôlées à l'enregistrement.
  • B2.1 Décrire comment un attaquant peut prendre le contrôle du compte d'un client connecté à Panier Vertalis, sans connaître son mot de passe, à partir du document B2. Nommer l'attaque.
  • B2.2 Modifier le formulaire et le traitement pour bloquer cette attaque. Indiquer les lignes ajoutées.
  • B3.1 Identifier l'algorithme de hachage actuel, la faille correspondante dans l'OWASP Top 10 2021, et expliquer pourquoi il n'est pas adapté.
  • B3.2 Écrire la partie du traitement de connexion qui vérifie le mot de passe saisi ($mel, $mdp) et remplace une ancienne empreinte MD5 par une empreinte password_hash() lors d'une connexion réussie.
  • B3.3 Indiquer ce qu'il faut prévoir pour les clients qui ne se reconnecteront jamais.
  • B4.1 Nommer la faille du document B3 et décrire comment un client malveillant l'exploite. Indiquer l'obligation qui pèse sur Vertalis si elle a été exploitée.
  • B4.2 Corriger le code. Indiquer les lignes modifiées ou ajoutées.
Voir la réponseMasquer la réponse de l'exercice 2

B1.1. C'est un XSS stocké (cross-site scripting), qui relève de l'injection (A03:2021). Le script est enregistré en base avec l'avis ; à chaque affichage de la page, il est renvoyé tel quel et le navigateur de chaque visiteur l'exécute (ici, une redirection vers un site publicitaire ; il pourrait aussi voler des cookies de session). Un XSS reflété ne touche que les personnes qui cliquent sur un lien piégé contenant le script ; le XSS stocké touche tous les visiteurs de la page produit, sans action de leur part, tant que l'avis n'est pas supprimé.

B1.2. Lignes 4 et 5 modifiées :

4.     echo '<div class="avis"><strong>' . htmlspecialchars($avis['pseudo'], ENT_QUOTES, 'UTF-8') . '</strong> ';
5.     echo (int) $avis['note'] . '/5<p>' . htmlspecialchars($avis['texte'], ENT_QUOTES, 'UTF-8') . '</p></div>';

htmlspecialchars transforme < et > en entités : le navigateur affiche <script> comme du texte au lieu de l'exécuter. Le pseudo est aussi une saisie de client : il doit être échappé. La note est forcée en entier. Il faut ensuite supprimer l'avis malveillant de la base.

B1.3. Le filtrage à l'enregistrement ne suffit pas : des données ont pu être enregistrées avant sa mise en place (c'est le cas ici), d'autres applications ou une API peuvent écrire dans la même table, et un filtre d'entrée peut être contourné par une forme d'écriture qu'il n'a pas prévue. L'échappement à l'affichage protège quelle que soit l'origine de la donnée, et il est adapté au contexte (HTML ici). Les deux mesures se complètent : c'est la défense en profondeur.

B2.1. C'est une attaque CSRF (cross-site request forgery, falsification de requête intersite). L'attaquant publie sur un autre site, ou envoie par courriel, une page contenant un formulaire caché qui envoie mel=attaquant@exemple.net vers traiter_mel.php et se soumet automatiquement. Si la victime est connectée à Panier Vertalis, son navigateur joint son cookie de session : le serveur voit une requête authentifiée et change l'adresse du compte. L'attaquant utilise ensuite « mot de passe oublié » : le lien de réinitialisation arrive dans sa boîte, il choisit un nouveau mot de passe et prend le compte (adresses, historique de commandes).

B2.2.

Dans mon_compte.php, avant la ligne 1 (ajout, 0a à 0c) et après la ligne 2 (ajout, 2a) :

php
0a. <?php if (empty($_SESSION['jetonCsrf'])) {
0b.     $_SESSION['jetonCsrf'] = bin2hex(random_bytes(32));
0c. } ?>
2a.     <input type="hidden" name="jeton" value="<?= htmlspecialchars($_SESSION['jetonCsrf']) ?>">

Dans traiter_mel.php, après la ligne 2 (ajout, 2a à 2c) :

php
2a. if (!isset($_POST['jeton']) || !hash_equals($_SESSION['jetonCsrf'] ?? '', $_POST['jeton'])) {
2b.     http_response_code(403); exit('Requête refusée');
2c. }

Le site de l'attaquant ne peut pas lire le jeton, aléatoire et propre à la session : sa requête forgée est refusée. hash_equals compare en temps constant. Mesures complémentaires : cookie de session SameSite=Lax, demande du mot de passe actuel pour modifier l'adresse, courriel d'alerte envoyé à l'ancienne adresse.

B3.1. L'algorithme est MD5 (empreinte de 32 caractères hexadécimaux, fonction md5()). C'est une défaillance cryptographique (A02:2021). MD5 est cassé et extrêmement rapide : un processeur graphique teste des milliards de mots de passe par seconde, et des tables précalculées donnent instantanément les mots de passe courants. Sans sel, deux clients qui ont le même mot de passe ont la même empreinte.

B3.2.

php
$stmt = $pdo->prepare("SELECT id, mdp FROM Client WHERE mel = :mel");
$stmt->execute([':mel' => $mel]);
$client = $stmt->fetch(PDO::FETCH_ASSOC);
$authentifie = false;
if ($client) {
    if (password_verify($mdp, $client['mdp'])) {
        $authentifie = true;                       // empreinte déjà migrée
    } elseif (preg_match('/^[a-f0-9]{32}$/', $client['mdp'])
              && hash_equals($client['mdp'], md5($mdp))) {
        $authentifie = true;                       // ancienne empreinte MD5 correcte
        $maj = $pdo->prepare("UPDATE Client SET mdp = :mdp WHERE id = :id");
        $maj->execute([':mdp' => password_hash($mdp, PASSWORD_DEFAULT), ':id' => $client['id']]);
    }
}
if ($authentifie) {
    session_regenerate_id(true);
    $_SESSION['idClient'] = $client['id'];
}

On ne peut recalculer une empreinte moderne qu'au moment où l'on connaît le mot de passe en clair, c'est-à-dire lors d'une connexion réussie. La colonne mdp doit être élargie (VARCHAR(255)) avant la migration.

B3.3. Les empreintes MD5 restantes sont toujours vulnérables. Il faut fixer une date limite au-delà de laquelle les comptes non migrés sont invalidés : leur empreinte est effacée et le client doit réinitialiser son mot de passe par courriel. Comme les empreintes MD5 ont pu être exposées (la base a été manipulée), il est prudent d'informer les clients et de leur conseiller de changer ce mot de passe s'ils l'utilisent ailleurs.

B4.1. C'est un contrôle d'accès défaillant (A01:2021, référence directe non sécurisée). La requête cherche la facture par son seul numéro, sans vérifier qu'elle appartient au client connecté. Comme les numéros se suivent, un client remplace F2027-00418 par F2027-00417, F2027-00416… et lit les factures des autres clients, avec leur adresse de livraison. Si la faille a été exploitée, c'est une violation de données à caractère personnel : Vertalis, responsable de traitement, doit la documenter et la notifier à la CNIL dans les meilleurs délais, si possible sous 72 heures, puisqu'elle présente un risque pour les personnes (article 33 du RGPD) ; Kodex, sous-traitant, doit l'en informer dans les meilleurs délais (article 33, paragraphe 2).

B4.2.

php
2a. if (!isset($_SESSION['idClient'])) { header('Location: connexion.php'); exit; }
4.                        FROM Facture WHERE numero = ? AND idClient = ?");
5. $stmt->execute([$num, $_SESSION['idClient']]);
6a. if (!$facture) { http_response_code(404); exit('Facture introuvable'); }

L'appartenance est vérifiée dans la requête, avec l'identifiant du client pris dans la session. Répondre 404 plutôt que 403 évite de confirmer l'existence d'une facture d'un autre client ; les deux réponses sont défendables.

Tu avais trouvé ?

Chapitre terminé !

Fais les 2 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Réviser l'E7 : calendrier, erreurs et fiches réflexesRevoir le sommaire du cours