Files
ENI-JSAdvanced_10/README.md
2025-12-18 15:21:19 +01:00

198 lines
7.6 KiB
Markdown

# Démonstration A07:2025 - Authentication Failures
## Objectif de la démonstration
Cet atelier illustre concrètement plusieurs vulnérabilités de la catégorie **A07:2025 - Authentication Failures** (échecs d'authentification) de l'owasp.
Vous n'avez **aucun code à écrire**. Votre rôle est d'analyser le comportement de deux points de terminaison (endpoints) à l'aide de postman et d'observer les journaux (logs) du serveur.
## Contexte du projet
Le code `routes/index.js` contient deux routes d'authentification:
1. `POST /login-vulnerable`: une implémentation intentionnellement faible.
2. `POST /login-securise`: une implémentation corrigée et sécurisée.
## Prérequis
* Node.js et npm installés.
* Le logiciel postman (ou un équivalent pour tester les api).
* Ce projet (avec les `node_modules` installés via `npm install`).
## Instructions de lancement
1. Ouvrez un terminal (par exemple, le terminal intégré de webstorm).
2. Lancez le serveur en mode "watch" avec la commande:
```bash
nodemon ./bin/www
```
3. Gardez cette console visible. C'est ici que vous lirez les journaux (logs) du serveur.
4. Ouvrez postman pour effectuer les tests décrits ci-dessous.
---
## Partie 1: Analyse du point de terminaison vulnérable
Testez l'endpoint `POST http://localhost:3000/login-vulnerable` avec postman.
Assurez-vous d'envoyer vos données en `raw` -> `json` dans l'onglet `Body`.
```mermaid
flowchart TD
a["client envoie requête vers /login-vulnerable"] --> b["serveur recherche l'utilisateur"]
b --> c{"utilisateur trouvé ?"}
c -- "non" --> d["retour 404 avec message 'utilisateur non trouvé'"]
c -- "oui" --> e{"mot de passe valable ?"}
e -- "non" --> f["retour 400 avec message 'mot de passe incorrect'"]
e -- "oui" --> g["session non régénérée"]
g --> h["retour 200 'connexion vulnérable réussie'"]
```
### Faille 1: énumération de comptes
L'énumération de comptes permet à un attaquant de deviner quels utilisateurs existent dans la base de données en analysant les différentes réponses du serveur.
**Test A: utilisateur inexistant**
* Requête (body):
```json
{
"username": "un_utilisateur_inconnu",
"password": "123"
}
```
* Réponse (status 404): `Erreur : Utilisateur non trouvé.`
**Test B: utilisateur existant, mauvais mot de passe**
* Requête (body):
```json
{
"username": "admin",
"password": "mauvais_mot_de_passe"
}
```
* Réponse (status 400): `Erreur : Mot de passe incorrect.`
**Conclusion de la faille 1:**
Les messages d'erreur sont différents. Un attaquant peut créer un script pour tester des milliers de noms d'utilisateurs et savoir lesquels sont valides (ceux qui retournent "mot de passe incorrect").
### Faille 2: mots de passe en clair et absence de limitation
Cette route compare directement le mot de passe reçu avec un mot de passe stocké en clair (`password_vulnerable`).
```mermaid
flowchart TD
a["client envoie requête vers /login-securise"] --> b["serveur recherche l'utilisateur (sans distinction dans la réponse)"]
b --> c["vérification avec 'bcrypt.compare'"]
c --> d{"identifiants valides ?"}
d -- "non" --> e["retour 401 'identifiants invalides'"]
d -- "oui" --> f["regeneration de la session"]
f --> g["retour 200 'connexion sécurisée réussie'"]
```
**Test C: attaque par force brute**
* Le serveur n'implémente aucune limitation de tentatives (rate limiting).
* Un attaquant pourrait tester des millions de mots de passe pour l'utilisateur "admin" sans jamais être bloqué.
### Faille 3: fixation de session
La fixation de session se produit lorsque l'identifiant de session d'un utilisateur n'est pas renouvelé après une authentification réussie.
**Test D: connexion réussie**
* Requête (body):
```json
{
"username": "admin",
"password": "password123"
}
```
* Réponse (status 200): `Connexion (vulnérable) réussie pour admin !`
* **Action requise:** regardez maintenant la console de votre serveur (dans webstorm).
* Vous devriez voir les logs suivants:
```
[VULNÉRABLE] Session AVANT login: [un long identifiant]
[VULNÉRABLE] Session APRÈS login: [le même identifiant] (INCHANGÉE)
```
**Conclusion de la faille 3:**
L'identifiant de session est le même avant et après le login. Si un attaquant parvenait à "fixer" (donner) un identifiant de session à un utilisateur avant sa connexion (par exemple, via un lien piégé), il pourrait usurper son identité une fois l'utilisateur connecté.
---
## Partie 2: Analyse du point de terminaison corrigé
Testez maintenant l'endpoint `POST http://localhost:3000/login-securise`.
### Correction 1: prévention de l'énumération de comptes
**Test A (corrigé): utilisateur inexistant**
* Requête (body):
```json
{
"username": "un_utilisateur_inconnu",
"password": "123"
}
```
* Réponse (status 401): `Identifiants invalides.`
**Test B (corrigé): utilisateur existant, mauvais mot de passe**
* Requête (body):
```json
{
"username": "admin",
"password": "mauvais_mot_de_passe"
}
```
* Réponse (status 401): `Identifiants invalides.`
**Conclusion de la correction 1:**
La réponse est identique dans les deux cas. Il est désormais impossible pour un attaquant de distinguer un nom d'utilisateur invalide d'un mot de passe invalide.
### Correction 2: hachage et régénération de session
**Test D (corrigé): connexion réussie**
* Le code utilise `bcrypt.compare` pour comparer de manière sécurisée le mot de passe fourni avec le hash stocké.
* Requête (body):
```json
{
"username": "admin",
"password": "password123"
}
```
* Réponse (status 200): `Connexion (sécurisée) réussie pour admin !`
* **Action requise:** regardez à nouveau la console du serveur.
* Vous devriez voir ces logs:
```
[SÉCURISÉ] Session AVANT login: [un premier identifiant]
[SÉCURISÉ] Session APRÈS login: [un nouvel identifiant] (CHANGÉE)
```
**Conclusion de la correction 2:**
Le serveur a explicitement régénéré la session (`req.session.regenerate`). L'ancien identifiant est invalidé et un nouveau est créé, empêchant toute attaque de type "fixation de session".
### Correction 3: limitation des tentatives (rate limiting)
**Test E (corrigé): attaque par force brute**
* Envoyez la requête du "Test B (corrigé)" (avec un mauvais mot de passe) 11 fois de suite.
* Les 10 premières tentatives renverront `Identifiants invalides.`
* À la 11ème tentative (et pour les suivantes pendant 15 minutes), vous recevrez:
* Réponse (status 429): `Trop de tentatives de connexion. Réessayez dans 15 minutes.`
**Conclusion de la correction 3:**
Le serveur empêche activement les attaques par force brute ou par "credential stuffing" en limitant le nombre d'échecs autorisés par adresse ip.
## Conclusion
Cette démonstration a mis en évidence plusieurs vulnérabilités courantes liées à l'authentification, ainsi que les mesures correctives appropriées pour les atténuer.
```mermaid
flowchart LR
a["vulnérabilité : énumération de comptes"] --> b["risque : découverte des utilisateurs valides"]
c["vulnérabilité : mots de passe en clair"] --> d["risque : compromission immédiate"]
e["vulnérabilité : pas de rate limiting"] --> f["risque : force brute illimitée"]
g["vulnérabilité : session non régénérée"] --> h["risque : fixation de session"]
i["mesure : message d'erreur uniforme"] --> a
j["mesure : mot de passe hashé"] --> c
k["mesure : rate limiting"] --> e
l["mesure : regeneration de session"] --> g
```