E6 — Cybersécurité des services informatiques

Yak — SLAM, session Novembre 2023

Méthodologie et corrigé commenté — E6 — Cybersécurité des services informatiques, BTS SIO.

  • Durée 2h10
  • Filière SLAM
  • Session Novembre 2023

Corrigé commenté Lockbay

Sujet officiel

Cas Yak (Yak-à-Partir) — Session 2023, U6/E6 (SLAM), code 23SI6SLAM-NC1, sur 80 points (Dossier A : 30 pts, Dossier B : 35 pts, Dossier C : 15 pts). 📄 Télécharger le sujet officiel Yak (réseaucerta.org)

Lockbay n’héberge pas le sujet : ce corrigé est une production originale Lockbay qui répond aux questions du sujet officiel. Sujet © Éducation nationale.

Le cas Yak (agence de voyages, prestataire Breizh-SN) couvre trois dossiers : sécuriser l’authentification et les habilitations de l’application Java Holy, fusionner deux bases dans le respect du RGPD et lutter contre l’injection SQL, puis renforcer la sécurité des applications Web (CSRF, journalisation, blocage de compte). Corrigé question par question.

Dossier A — Authentification et habilitations de l'application Holy 30 pts

Mission A1 — Bonnes pratiques pour la classe Utilisateur

A1.1

Corriger les erreurs de nommage de ancienMdp

Selon les règles Java (doc. A5), une méthode renvoyant un booléen de vérification doit refléter une action (verbe) et le paramètre doit être descriptif (pas la lettre seule m en usage non local). On renomme ancienMdp(String m) en estAncienMdp(String mdp), le corps restant identique (parcours de lesAnciensMdp, comparaison equals(mdp)).

A1.2

Documentation Javadoc

/**
 * Vérifie si le mot de passe passé en paramètre figure
 * parmi les anciens mots de passe de l'utilisateur.
 * @param mdp le mot de passe à rechercher dans l'historique
 * @return vrai si ce mot de passe a déjà été utilisé, faux sinon
 */

Mission A2 — Validation des mots de passe

A2.1

Complexité attendue

D’après la méthode verifierMdp (doc. A3), un mot de passe valide doit respecter toutes ces règles :

CritèreExigence
Longueur≥ 12 caractères
Majuscules≥ 1
Minuscules≥ 3
Chiffres≥ 4
Caractères spéciaux≥ 1 (plage ASCII 33–46, ou @ = 64)
A2.2

Méthode modifierMdp

Elle doit : vérifier la complexité, vérifier que le mot de passe n’est pas un ancien, archiver le mot de passe actuel dans l’historique, puis le remplacer.

public boolean modifierMdp(String valMdp) {
    boolean ok = false;
    if (this.verifierMdp(valMdp) && !this.estAncienMdp(valMdp)) {
        // archive le mot de passe actuel avec la date du jour
        this.lesAnciensMdp.add(new MotDePasse(this.motDePasse, LocalDate.now()));
        this.motDePasse = valMdp;
        ok = true;
    }
    return ok;
}

Mission A3 — Validation de l’authentification

A3.1

Méthode de test verifModifierMdp

D’après init() (doc. A4), le mot de passe courant après les deux appels est "M1ue@uiT455n" et l’historique contient "Coe8@MatH279" et "Lae99_Mat00!". On teste un cas valide, un mot de passe trop faible et un ancien mot de passe.

@Test
void verifModifierMdp() {
    // mot de passe valide et inédit -> accepté
    assertTrue(unUtilisateur.modifierMdp("Nouv3au@MdP12"));
    // mot de passe trop simple (règles non respectées) -> refusé
    assertFalse(unUtilisateur.modifierMdp("azerty"));
    // ancien mot de passe -> refusé
    assertFalse(unUtilisateur.modifierMdp("Coe8@MatH279"));
}
A3.2

Scénario de risque (absence de restriction d’accès au menu)

Un salarié n’ayant que des droits de consultation accède malgré tout, via le menu non restreint, aux fonctions d’édition comptable ou de suppression de contrats, et peut modifier ou supprimer des données financières (volontairement ou par erreur) → atteinte à l’intégrité des données. La restriction applique le moindre privilège : chacun ne voit que les fonctions de son niveau d’habilitation.

A3.3

a) Méthode getNiveauHabilitation — elle retourne le niveau de l’habilitation portée par l’utilisateur :

public int getNiveauHabilitation() {
    return this.sonHabilitation.getNiveau();
}

b) Constructeur d’AppliHoly — rendre accessibles uniquement les éléments de menu dont le niveau requis est inférieur ou égal à celui de l’utilisateur connecté :

for (ElementMenu unElement : lesElementsMenu) {
    if (unElement.getNiveauHabilitation() <= leUtilConnecte.getNiveauHabilitation()) {
        unElement.rendreAccessible();
    }
}
Dossier B — Sécurisation de la fusion des bases de données 35 pts

Mission B1 — Sécuriser les données personnelles

B1.1

Tableau données personnelles / données sensibles

Les données sensibles au sens du RGPD (art. 9) révèlent la santé, l’origine, etc. La table Client de Désir d’Ailleurs contient notamment numPièceIdentité, nationalité et estAMobilitéRéduite (donnée de santé).

BaseDonnées personnellesDonnées sensibles
EchapBoxcivilité, nom, prénom, dateNaiss, pseudo, mdp, adresse, codePostal, ville, pays, tél, mél(aucune)
Désir d’Ailleurscivilité, nom, prénom, dateNaiss, pseudo, mdp, adresse, tél, mél, n° et type de pièce d’identité, nationalitéétat de mobilité réduite (santé/handicap), nationalité
B1.2

Ajout du champ accordPubli

ALTER TABLE Client
    ADD accordPubli BOOLEAN DEFAULT FALSE;
B1.3

Corps du courriel (consentement éclairé)

Objet : Fusion de nos bases clients et votre consentement au démarchage commercial

Bonjour,

Yak-à-Partir réunit les données de ses services Désir d’Ailleurs et EchapBox au sein d’une base unique, afin de simplifier la gestion et de mieux sécuriser vos informations. Aucun nouvel usage de vos données n’est prévu : les applications fonctionneront comme aujourd’hui.

Nous souhaitons par ailleurs vous adresser ponctuellement nos offres commerciales par publipostage. Cet envoi est facultatif et nécessite votre accord.

Pour le donner, rendez-vous sur https://www.EchapBox.com/accordPubli et validez le formulaire. Sans action de votre part, aucun démarchage ne vous sera adressé (accord refusé par défaut). Vous disposez d’un mois pour répondre.

Conformément au RGPD, vous pouvez à tout moment retirer votre consentement et exercer vos droits d’accès, de rectification et d’effacement.

Cordialement, l’équipe Yak-à-Partir.

B1.4

Conserver une trace du consentement et garantir son intégrité

Pour la valeur probante exigée par le RGPD, on journalise chaque recueil de consentement dans une table dédiée (ou un fichier de log) : identifiant client, date/heure, version du texte présenté, source (formulaire). Pour garantir l’intégrité de cette trace :

  • calcul d’une empreinte (hash, ex. SHA-256) de chaque enregistrement, voire chaînage des empreintes (chaque ligne intègre le hash de la précédente) ;
  • accès en écriture restreint (write-once / ajout seul), horodatage fiable ;
  • archivage à valeur probante et sauvegarde, afin qu’aucune modification a posteriori ne passe inaperçue.
B1.5

Structure de la table ClientAnonyme (minimisation)

Pour des statistiques par genre, tranche d’âge et département, on ne conserve que le strict nécessaire, sous une forme non identifiante : pas de nom, prénom, adresse exacte, contact ni pseudo.

EchapBox.ClientAnonyme(id, civilité, anneeNaiss, codeDépartement)
La clé primaire est id.

(On peut remplacer dateNaiss par l’année — ou directement une tranche d’âge — et le codePostal par les deux premiers chiffres pour le département, ce qui empêche la réidentification.)

Mission B2 — Détecter les agissements frauduleux

B2.1

Justifier la gravité de R1 et R2

  • R1 (acompte ≥ montant à payer) : par injection SQL, un client crée/modifie un contrat où l’acompte couvre déjà la totalité → la facture du solde est nulle ou négative. L’entreprise réalise une prestation non payée, voire rembourse indûment : préjudice financier direct et potentiellement répété → gravité élevée.
  • R2 (montant à payer inférieur à 75 €/pers/jour) : un client contourne le tarif plancher de l’agence → marge effondrée, prestations vendues à perte. Cumulé, l’impact menace la rentabilité de l’activité → gravité élevée.

Dans les deux cas, l’origine injection SQL signifie aussi une atteinte à l’intégrité de la base et une perte de confiance.

B2.2

Requête de détection (acompte ≥ montant à payer)

SELECT c.idCli, c.nom, c.prenom
FROM Client c
JOIN Contrat_Voyage cv ON cv.idCli = c.idCli
WHERE cv.acompte >= cv.montantAPayer;
B2.3

Compléter le trigger (montant minimum 75 €/pers/jour)

On ajoute, après le contrôle de durée, la vérification que le montant à payer atteint au moins 75 € × nombre de jours × nombre de participants :

SET @nb_part = ( SELECT nbParticipants FROM Devis_Voyage
                 WHERE idDevis = NEW.idDevis );
IF NEW.montantAPayer < 75 * @nb_jours * @nb_part THEN
    SIGNAL SQLSTATE '10002'
       SET MESSAGE_TEXT = 'Le montant à payer est inférieur au minimum de 75 euros par participant et par jour';
END IF;
Dossier C — Amélioration de la sécurité des applications Web 15 pts

Mission C1 — Conformité de la protection CSRF

C1.1

Fonctionnement de la protection en place

Le code (doc. C3) utilise un jeton anti-CSRF (token). À l’affichage du formulaire (modifMdp.php), le jeton stocké en session est inséré dans un champ caché. Au traitement (traitement.php), le serveur compare le jeton reçu par POST avec celui de la session : le traitement ne s’exécute que s’ils sont tous deux présents et identiques.

Un site malveillant ignorant la valeur du jeton (propre à la session de la victime) ne peut pas forger de requête valide : elle est rejetée (« Erreur de vérification »). La protection repose sur un secret partagé serveur ↔ formulaire légitime.

Mission C2 — Analyse des fichiers de journalisation

C2.1

a) Événements présents dans l’extrait du 10/05/2023 :

  • une erreur de connexion isolée (AllanG, 21:41:18) ;
  • un essai avec champs vides (WARNING, 21:41:20) ;
  • une rafale d’erreurs de connexion pour RichardP (≥ 9 échecs en quelques secondes) ;
  • une connexion réussie de AllanG (21:41:26).

b) Note au responsable :

Les échecs répétés et très rapprochés sur le compte RichardP (plusieurs par seconde) ne correspondent pas à un comportement humain. Mon hypothèse : une attaque par force brute / bourrage d’identifiants automatisée visant ce compte. Je recommande de verrouiller temporairement le compte après un seuil d’échecs, de limiter le débit des tentatives, et d’alerter l’utilisateur.

C2.2

Évolution de la base (tentatives de connexion)

Un utilisateur peut faire plusieurs tentatives ; une tentative appartient à un seul utilisateur et porte un résultat (réussite/échec). On ajoute une table en relation 1‑N avec Client.

a) Structure proposée :

TentativeConnexion(idTentative, dateHeure, resultat, #idCli)
La clé primaire est idTentative ; idCli est clé étrangère vers Client.

b) Deux enregistrements pour un même utilisateur :

idTentativedateHeureresultatidCli
12023-05-10 21:41:24échec42
22023-05-10 21:41:26échec42
C2.3

Désactivation temporaire d’un compte (sans l’implémenter)

Ajouter à la table Client un attribut booléen, par exemple actif (valeur par défaut VRAI). Lorsque le nombre d’échecs récents dépasse un seuil, l’application passe actif à FAUX ; à chaque tentative de connexion, on vérifie d’abord cet indicateur et on refuse l’accès tant qu’il est faux. L’administrateur, après vérification, peut réactiver le compte (remise à VRAI) ou prendre d’autres mesures. Cette approche désactive sans supprimer : aucune donnée n’est perdue et la réactivation est immédiate.

Points de barème (rappel)

DossierAttenduPoints
ABonnes pratiques de nommage + Javadoc, complexité et modifierMdp, test unitaire, scénario de risque, habilitations (menu)30
BDonnées personnelles/sensibles, ALTER TABLE consentement, courriel RGPD, traçabilité + intégrité, minimisation, gravité injection SQL, requête de contrôle, trigger 75 €35
CFonctionnement du jeton anti-CSRF, analyse des journaux (brute force), table des tentatives, désactivation de compte15
TotalDossier A 30 + Dossier B 35 + Dossier C 1580
Sujet officiel © Éducation nationale — publié par le Réseau CERTA — Éducation nationale (lien source). Corrigé commenté et méthodologie © Lockbay Academy.