6.1 KiB
Démonstration OWASP A02 : mauvaise configuration de sécurité (CORS)
Objectif
Comprendre la faille de sécurité OWASP A02:2025 (Security Misconfiguration) à travers une démonstration concrète sur CORS (Cross-Origin Resource Sharing).
Dans cet exercice, vous n'allez pas coder. Vous allez manipuler la configuration d'un serveur Express.js pour observer la différence entre une configuration vulnérable et une configuration sécurisée.
Contexte
Nous avons deux projets:
cors: un serveur Express (back-end) qui tourne surhttp://localhost:3000.- sous-répertoire
client-test: un simple fichierindex.html(front-end) qui sera servi par votre IDE (sur un port dynamique, ex:http://localhost:63342).
Le client (d'une certaine origine) va tenter d'appeler l'API (sur une autre origine). Nous allons voir comment CORS peut bloquer ou autoriser cet appel.
flowchart LR
subgraph "Client (Navigateur)"
ClientApp["index.html<br>Origine: http://localhost:63342"]
end
subgraph "Serveur (API)"
ServerApp["app.js (Express)<br>Origine: http://localhost:3000"]
end
ClientApp -- "Tente d'appeler l'API" --> ServerApp
Instructions
Mise en place
- Ouvrez un terminal et placez-vous dans le dossier
cors. - Installez les dépendances:
npm install - Ouvrez le fichier
client-test/index.htmlavec votre IDE (clic droit > "Run 'index.html'" ou similaire). - Gardez cette page navigateur ouverte. Elle vous indique sa propre origine (ex:
http://localhost:63342). Notez-la.
Partie 1 : la vulnérabilité (origin: '*')
Dans cette partie, nous allons voir pourquoi origin: '*' est une mauvaise configuration de sécurité.
- Ouvrez le fichier
cors/app.js. - Vérifiez que c'est bien
corsOptions_VULNERABLEqui est activé:// DÉCOMANDEZ L'OPTION QUE VOUS VOULEZ TESTER : app.use(cors(corsOptions_VULNERABLE)); // <--- CETTE LIGNE DOIT ÊTRE ACTIVE // // app.use(cors(corsOptions_SECURISEE)); - Lancez le serveur API dans votre terminal (depuis le dossier
cors):(Le serveur tourne maintenant surnodemon ./bin/wwwhttp://localhost:3000) - Retournez sur votre page
index.htmldans le navigateur. - Cliquez sur le bouton "Appeler l'API".
Résultat attendu: succès. La page affiche les données JSON de l'API.
Pourquoi c'est une faille:
L'API a répondu. C'est normal, car origin: '*' signifie "J'autorise n'importe quel site web sur Internet à m'appeler". Si cette page était un site de phishing, elle aurait pu récupérer vos données. C'est une faille A02.
sequenceDiagram
participant Client as "Client<br>localhost:63342"
participant Serveur as "Serveur<br>localhost:3000"
Client->>Serveur: "1. Requete API (Origin: localhost:63342)"
Serveur-->>Serveur: 2. Verifie config CORS: origin: '*'
Serveur->>Client: "3. Reponse API (Access-Control-Allow-Origin: *)"
Client-->>Client: 4. Navigateur autorise<br>Succes!
Partie 2 : la correction (Whitelist)
Maintenant, nous allons corriger la faille en n'autorisant que notre client légitime.
-
Arrêtez le serveur API (
Ctrl+Cdans le terminal). -
Dans
cors/app.js, modifiez les lignesapp.usepour activer la version sécurisée:// DÉCOMANDEZ L'OPTION QUE VOUS VOULEZ TESTER : // app.use(cors(corsOptions_VULNERABLE)); // app.use(cors(corsOptions_SECURISEE)); // <--- CETTE LIGNE DOIT ÊTRE ACTIVE -
Dans ce même fichier, juste au-dessus, modifiez la variable
corsOptions_SECURISEEpour qu'elle corresponde exactement à l'origine affichée sur votre pageindex.html.Exemple: si votre page affiche
http://localhost:63342, le code doit être:const corsOptions_SECURISEE = { origin: 'http://localhost:63342' }; -
Sauvegardez
app.jset relancez le serveur API:nodemon ./bin/www -
Retournez sur votre page
index.htmlet rafraîchissez-la (Ctrl+RouCmd+R). -
Cliquez sur le bouton "Appeler l'API".
Résultat attendu: succès. Les données s'affichent, comme dans la partie 1.
Alors, quelle est la différence ? La différence est que maintenant, seule cette origine est autorisée. Pour le prouver, faisons un dernier test.
Partie 3 : la preuve de la sécurité
Prouvons que notre API rejette bien les origines inconnues.
- Arrêtez le serveur API (
Ctrl+C). - Dans
cors/app.js, modifiezcorsOptions_SECURISEEpour y mettre une fausse origine:const corsOptions_SECURISEE = { origin: '[http://site-malveillant.com](http://site-malveillant.com)' }; - Sauvegardez
app.jset relancez le serveur API:nodemon ./bin/www - Retournez sur votre page
index.html(qui tourne toujours surhttp://localhost:63342) et rafraîchissez-la. - Ouvrez la console de développement (F12) et allez dans l'onglet "Console".
- Cliquez sur le bouton "Appeler l'API".
Résultat attendu: échec. La page affiche ERREUR: Failed to fetch.
Pourquoi c'est corrigé: Regardez la console du navigateur. Vous y verrez une erreur CORS en rouge. Le navigateur a bloqué la requête car:
- Le client (
http://localhost:63342) a demandé des données. - Le serveur a répondu: "Je n'autorise que
http://site-malveillant.com". - Le navigateur a comparé les deux, a vu qu'ils ne correspondaient pas, et a bloqué la réponse pour protéger l'utilisateur.
Nous avons corrigé la faille A02:2025, notre API ne parle désormais qu'aux clients qu'elle connaît et approuve.
sequenceDiagram
participant Client as "Client<br>localhost:63342"
participant Serveur as "Serveur<br>localhost:3000"
Client->>Serveur: "1. Requete API (Origin: localhost:63342)"
Serveur-->>Serveur: 2. Verifie config CORS: origin: 'http://site-malveillant.com'
Serveur->>Client: "3. Reponse API (Access-Control-Allow-Origin: http://site-malveillant.com)"
Client-->>Client: 4. Navigateur compare:<br>Requete "localhost:63342" != Reponse "site-malveillant.com"
Client-->>Client: 5. ECHEC: Erreur CORS