E6: IT services cybersecurity

Yak - SLAM, November 2023 session

Methodology and annotated worked solution: E6: IT services cybersecurity, BTS SIO.

  • Duration 2h10
  • Pathway SLAM
  • Session November 2023

Lockbay annotated solution

Official exam paper

Yak case study (Yak-à-Partir) - 2023 session, U6/E6 (SLAM), code 23SI6SLAM-NC1, out of 80 points (Part A: 30 pts, Part B: 35 pts, Part C: 15 pts). 📄 Download the official Yak exam paper (réseaucerta.org)

Lockbay does not host the exam paper: this model answer is an original Lockbay production answering the questions from the official paper. Exam paper © Éducation nationale.

The Yak case study (travel agency, Breizh-SN service provider) covers three parts: securing authentication and permissions for the Holy Java application, merging two databases in compliance with GDPR and countering SQL injection, then strengthening web application security (CSRF, logging, account lockouts). Question-by-question solutions.

Part A - Authentication and permissions for the Holy application 30 pts

Task A1 - Best practices for the Utilisateur class

A1.1

Fix naming errors in ancienMdp

According to Java rules (doc. A5), a method returning a verification boolean must reflect an action (verb) and the parameter must be descriptive (not the single letter m in non-local use). We rename ancienMdp(String m) to estAncienMdp(String mdp), with the body remaining identical (iterating over lesAnciensMdp, comparing equals(mdp)).

A1.2

Javadoc documentation

/**
 * 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
 */

Task A2 - Password validation

A2.1

Expected complexity

According to the verifierMdp method (doc. A3), a valid password must meet all of these rules:

CriterionRequirement
Length≥ 12 characters
Uppercase≥ 1
Lowercase≥ 3
Digits≥ 4
Special characters≥ 1 (ASCII range 33-46, or @ = 64)
A2.2

modifierMdp method

It must: verify complexity, check that the password is not an old one, archive the current password in the history, then replace it.

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;
}

Task A3 - Authentication validation

A3.1

verifModifierMdp test method

According to init() (doc. A4), the current password after the two calls is "M1ue@uiT455n" and the history contains "Coe8@MatH279" and "Lae99_Mat00!". We test a valid case, an overly weak password, and an old password.

@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

Risk scenario (lack of menu access restrictions)

An employee with read-only permissions still accesses accounting editing or contract deletion functions via the unrestricted menu, and can modify or delete financial data (deliberately or accidentally) → breach of data integrity. The restriction applies least privilege: each user only sees the functions matching their authorisation level.

A3.3

a) Method getNiveauHabilitation - it returns the user's authorisation level:

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

b) AppliHoly constructor - make accessible only those menu items whose required level is less than or equal to that of the logged-in user:

for (ElementMenu unElement : lesElementsMenu) {
    if (unElement.getNiveauHabilitation() <= leUtilConnecte.getNiveauHabilitation()) {
        unElement.rendreAccessible();
    }
}
Part B - Securing the database merge 35 pts

Task B1 - Securing personal data

B1.1

Personal data / sensitive data table

Sensitive data under the GDPR (Art. 9) reveals health, origin, etc. The Client table in Désir d’Ailleurs notably contains numPièceIdentité, nationalité and estAMobilitéRéduite (health data).

DatabasePersonal dataSensitive data
EchapBoxtitle, surname, first name, date of birth, username, password, address, postcode, city, country, phone, email(none)
Désir d’Ailleurstitle, surname, first name, date of birth, username, password, address, phone, email, ID document number and type, nationalityreduced mobility status (health/disability), nationality
B1.2

Adding the accordPubli field

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

Email body (informed consent)

Subject: Merger of our customer databases and your consent to direct marketing

Hello,

Yak-à-Partir is merging data from its Désir d’Ailleurs and EchapBox services into a single database to simplify management and better secure your information. No new use of your data is planned: the applications will continue to operate as they do today.

We would also like to occasionally send you marketing offers by direct mail. Receiving them is optional and requires your consent.

To give your consent, go to https://www.EchapBox.com/accordPubli and submit the form. If you take no action, no direct marketing will be sent to you (consent is refused by default). You have one month to respond.

In accordance with the GDPR, you can withdraw your consent at any time and exercise your rights of access, rectification and erasure.

Kind regards, the Yak-à-Partir team.

B1.4

Retaining proof of consent and ensuring its integrity

To achieve the probative value required by the GDPR, every collection of consent is logged in a dedicated table (or log file): customer ID, date/time, version of the text presented, source (form). To ensure the integrity of this record:

  • calculating a hash (e.g. SHA-256) for each record, or even hash chaining (each row includes the hash of the previous one);
  • restricted write access (write-once / append-only), reliable timestamping;
  • archiving with probative value and backups, so that no subsequent modification goes unnoticed.
B1.5

Structure of the ClientAnonyme table (minimisation)

For statistics by gender, age group and department, only what is strictly necessary is retained, in a non-identifiable form: no surname, first name, exact address, contact details or username.

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

(You can replace dateNaiss with the year - or directly an age group - and codePostal with the first two digits for the department, which prevents re-identification.)

Mission B2 - Detecting fraudulent activity

B2.1

Justify the severity of R1 and R2

  • R1 (deposit ≥ amount payable): via SQL injection, a customer creates/modifies a contract where the deposit already covers the full amount → the final balance invoice is zero or negative. The company provides an unpaid service, or even issues an undue refund: direct and potentially repeated financial loss → high severity.
  • R2 (amount payable below 75 €/person/day): a customer bypasses the agency's floor price → collapsed margin, services sold at a loss. Cumulatively, the impact threatens business profitability → high severity.

In both cases, the SQL injection origin also means compromised database integrity and a loss of trust.

B2.2

Detection query (deposit ≥ amount payable)

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

Complete the trigger (minimum amount 75 €/person/day)

After checking the duration, we add a check ensuring that the amount payable is at least 75 € × number of days × number of 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 - Improving web application security 15 pts

Mission C1 - CSRF protection compliance

C1.1

How the current protection works

The code (doc. C3) uses an anti-CSRF token (token). When the form is displayed (modifMdp.php), the token stored in the session is inserted into a hidden field. Upon processing (traitement.php), the server compares the token received via POST with the one in the session: processing only runs if both are present and identical.

A malicious site unaware of the token value (specific to the victim's session) cannot forge a valid request: it is rejected ("Verification error"). Protection relies on a shared secret: server ↔ legitimate form.

Mission C2 - Log file analysis

C2.1

a) Events present in the extract from 10/05/2023:

  • an isolated login error (AllanG, 21:41:18);
  • an attempt with empty fields (WARNING, 21:41:20);
  • a burst of login errors for RichardP (≥ 9 failures in a few seconds);
  • a successful login by AllanG (21:41:26).

b) Note to the manager:

The repeated, rapid failures on the RichardP account (several per second) do not match human behaviour. My hypothesis: an automated brute-force / credential-stuffing attack targeting this account. I recommend temporarily locking the account after a threshold of failed attempts, rate-limiting attempts, and alerting the user.

C2.2

Database changes (login attempts)

A user can make multiple attempts; an attempt belongs to a single user and has an outcome (success/failure). We add a table in a 1-N relationship with Client.

a) Proposed structure:

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

b) Two records for the same user:

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

Temporary account deactivation (without implementation)

Add a boolean attribute to the Client table, for example actif (default value TRUE). When the number of recent failures exceeds a threshold, the application sets actif to FALSE; on each login attempt, this indicator is checked first and access is denied as long as it is false. Following verification, the administrator can reactivate the account (resetting it to TRUE) or take other measures. This approach deactivates without deleting: no data is lost and reactivation is immediate.

Marking scheme points (reminder)

SectionExpectationPoints
ANaming best practices + Javadoc, complexity and modifierMdp, unit tests, risk scenario, permissions (menu)30
BPersonal/sensitive data, ALTER TABLE consent, GDPR email, traceability + integrity, minimisation, SQL injection severity, check query, 75 € trigger35
CHow the anti-CSRF token works, log analysis (brute force), attempts table, account deactivation15
TotalDossier A 30 + Dossier B 35 + Dossier C 1580
Official exam paper © Éducation nationale - published by Réseau CERTA - Éducation nationale (source link). Annotated solutions and methodology © Lockbay Academy.