--- title: 'Sécurité application web TP-1' disqus: Brice Allenet --- Sécurité application web | TP-1 === ## Table of Contents [TOC] # Part 1 ## Création d’un serveur HTTPs node.js en utilisant un certificat auto signé. La première étape de ce TP est de créer un serveur HTTPS en utilisant un certificat auto-signé. Créer un serveur HTTPS avec un certificat auto-signé est utile pour assurer une communication sécurisée entre un client et un serveur. Le protocole HTTPS utilise une couche de **chiffrement SSL/TLS** pour protéger les données échangées pendant la transmission. Le **certificat SSL** permet de garantir l'identiter entre deux personne, il s'agit en quelques sorte d'une "carte d'identité". Dans notre cas, nous utiliserons un certificat auto-signé, ce qui signifie qu'aucune autorité de certification supérieur ne validera notre certificat, autrement dit, le processus d'approbation ne sera pas complet. Le certificat auto-signé peut ne pas être en mesure de prouver l'authenticité du serveur, mais il a l'avantage de chiffrer les données échangées entre le client et le serveur. Dans le cadre d'un développement ou de tests internes, l'utilisation d'un certificat auto-signé est une solution pratique pour tester les fonctionnalités de l'application tout en assurant une communication chiffrée. Afin de mettre en place ce certificat nous procéderons par étapes comme suit : ### Génération du certificat auto-signé Pour cela nous utilisons la commande suivante : *openssl req -nodes -new -x509 -keyout server.key -out server.cert* Cette commande nous génère un cetificat et sa clé. Une fois le certificat généré, on le place, ainsi que la clé, à la racine de notre projet web. ### Implémentation de notre certificat dans le serveur JS Maintenant, nous allons implémenter le certificat sur un serveur que nous allons créer **"servercsrftCert.js"**. Pour implémenter le certificat, après avoir crée le fichier, nous y ajoutons les lignes suivantes : ```gherkin= const fs = require('fs'); const path = require('path'); const https = require('https'); const express = require('express'); /* On créer notre application Express */ const app = express(); /* On récupère notre clé privée et notre certificat (ici ils se trouvent dans le dossier certificate) */ const key = fs.readFileSync(path.join(__dirname, 'certificate', 'server.key')); const cert = fs.readFileSync(path.join(__dirname, 'certificate', 'server.cert')); const options = { key, cert }; /* Puis on créer notre serveur HTTPS */ https.createServer(options, app).listen(4000, () => { console.log('App is running ! Go to https://localhost:8080'); }); ``` Maintenant que cela est fait nous pouvons lancer le serveur grâce à node avec la commane **"node servercsrftCert.js"** Nous remarquons alors que la page est bien en HTTPS ! ![](https://i.imgur.com/JkJEri4.png) A noté que lors du chargement de la page une erreur de sécurité est levé, cela est du aufait qu'il s'agisse d'un certificat auto-signé et donc non reconnu par notre navigateur. # Part 2 Découvert de l'attaque CSRf --- Le Cross-Site Request Forgery (CSRF) est une faille de sécurité sur le web qui permet à un individu malveillant de contraindre un utilisateur à accomplir une action non souhaitée sur un site web pour lequel l'utilisateur est authentifié. Cette attaque se base sur les "cookie" utilisateur afin d'usurper l'identitée d'un utilisateur. Dans cette partie nous allons explorer cette attaque ainsi que ses contres-mesures. Tous les fichiers utilisés lors de ce test sont disponible en annexe. Dans un premier temps nous utilisons le serveur **"servercsrf1.js"** qui nous permet de simmuler des "échanges bancaire" entre deux personnes : Alice et Bob. Ensuite, nous nous connectons avec Bob sur le Client. Notez bien que nous avons supprimé tous les cookie de la page pour repartir de zéro. ![](https://i.imgur.com/429GZh6.png) ![](https://i.imgur.com/9wtdGeY.png) On remarque que Bob possède **un solde de 100** Du côté d'Alice, **le solde est lui de 500 **: ![](https://i.imgur.com/IGlr39L.png) Maintenant, afin de simmuler un attaquant nous allons lancer un deuxième serveur hébergé sur le port 8080, le code de ce serveur est le suivant : ```gherkin= const http = require('http'); const ecstatic = require('ecstatic'); const port = 8080; const staticHandler = ecstatic({ root: __dirname }); http.createServer(staticHandler).listen(port, function() { console.log(`Server running on port ${port}`); }); La page qui lui est lié est une page simmilaire à celle de transfert d'Alice ou de Bob mais ne comporte aucune page d'authentification. ``` ![](https://i.imgur.com/lhO0LPQ.png) Nous remarquons cependant que l'attaquant est authentifié en temps que Bob. ![](https://i.imgur.com/fK1KpFF.png) ![](https://i.imgur.com/jIYwSSh.png) Nous remarquons également, que sans effectuer de virement le solde de Bob est maintenant à 0 et celui de Alice à 600 ! Un transactions à donc été effectuée au non de Bob. Cela s'explique par le fait qu'une attaque CSRF se produit lorsque l'utilisateur est connecté à un site web, et qu'il ouvre une autre page web malveillante, qui contient un code spécialement conçu pour exploiter cette vulnérabilité. Ce code peut inclure une requête HTTP qui force le navigateur de l'utilisateur à effectuer une action sur le site web authentifié, sans le consentement de l'utilisateur. ## Patch de la vulnérabilité L'un des moyen de ce premunir de cette vulnérabilité est de mettre en place en login à base de cookie de session. our ajouter une protection CSRF, nous pouvons donc utiliser le middleware csurf de Express. Il faut l'installer via la commande suivante : ```gherkin= npm install csurf ``` Ensuite, nous pouvons l'ajouter au code du serveur en utilisant les étapes suivantes : 1. Importer csurf ```gherkin= const csrf = require('csurf'); ``` 2. Initialiser csrf : ```gherkin= const csrfProtection = csrf({ cookie: true }); ``` 3. Ajouter csrfProtection comme middleware pour toutes les routes qui nécessitent une protection CSRF. Dans notre cas, cela inclut la route transfer. Nous devons également ajouter un champ caché contenant le jeton CSRF à notre formulaire de transfert. ```gherkin= app.post('/transfer',csrfProtection, (req, res) => { const sessionId = req.cookies.sessionId; const username = SESSIONS[sessionId] if (!username) { res.send('fail!'); return } const amount = Number(req.body.amount) const to = req.body.to BALANCES[username] -= amount; BALANCES[to] += amount res.redirect('/') }); ``` Ce faisant, en tentant de relancer le script de l'attaquant nous obtenons le message suivant : ![](https://i.imgur.com/0pUmQk3.png) Le "CRSF token" fait référence au cookie de session sécurisé que nous avons mis en place. L'attaquant ne le possédant pas, il ne peux pas voir accès aux accès de Bob. ### HttpOnly et Secure Pour terminer, nous allons sécuriser le cookie de session que nous venons d'implémenter. Pour ce faire nous allons y ajouter la balise HttpOnly qui empêche les scripts type JS côté client d'y accéder. Cette mesure de sécurité rend les cookies plus sûrs en réduisant le risque d'attaque par des scripts malveillants. De plus, il est possible de renforcer un cookie en le marquant comme "sécurisé", ce qui indique qu'il ne sera envoyé que via une connexion HTTPS sécurisée. Cette précaution permet de prévenir les attaques d'interception de cookies par des pirates qui surveillent la communication entre le navigateur et le serveur. Nous n'en ferons cependant pas le test ici. Pour vérifier cela nous effectuer le test avec le porgramme JS suivant : ```gherkin= function getCookie(cName) { const name = cName + "="; const cDecoded = decodeURIComponent(document.cookie); //to be careful const cArr = cDecoded.split('; '); let res; cArr.forEach(val => { if (val.indexOf(name) === 0) res = val.substring(name.length); }) return res } ``` Le **résultat sans HTTPOnly** est le suivant : ![](https://i.imgur.com/66qNJoe.png) Nous pouvons récupérer le cookie de sessionId sans soucis. Maintenant nous refaisons le test après avoir ajouté l'attriue httponly sur notre cookie de session : ```gherkin= res.cookie('sessionId', nextSessionId, {httpOnly:true}); ``` Le **résultat avec HTTPOnly** est le suivant : ![](https://i.imgur.com/XWd49Cc.png) On remarque donc que le test est concluant et que le httponly empêche bien la récupération de cookie via un script JS. ###### tags: `ENSIBS` `Sécurité applications WEB` `Brice Allenet` `TD3` `TP5`