lafondoc
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Projet 2 SR03: Application de banque en ligne sécurisée Ce rapport est réalisé par Valentin CHELLE & Colin LAFOND pour le semestre P20. Il présente une liste des bonnes pratiques pour sécuriser une application web, ainsi qu'une synthèse sur un autre type de sécurité web qui n'a pas été étudié en cours. **Il est recommandé de lire ce rapport directement sur Gitlab, afin d'avoir un meilleur formatage du fichier et de ne pas voir de troncatures dues à la conversion Markdown -> PDF.** Liens git du projet : https://gitlab.utc.fr/chelleva/sr03-td-securite/ ## Organisation du projet : Pour réaliser le projet, nous sommes partis de l'application web utilisée, et corrigée en TD (pas la correction distribuée après coups sur Mattermost, mais notre propre correction). Nous l'avons ensuite réécrite de manière modulaire, en respectant le modèle MVC, et effectué toutes les améliorations sur cette base de code. Tout est sut Gitlab : - Le site web complet est disponible dans le dossier `site-web/` - Les scripts SQL sont disponibles dans le dossier `sql/`. Ils doivent être exécutés dans cet ordre : 1. `devoir_sr03_users_create.sql` 2. `devoir_sr03_users_insert.sql ` 3. `devoir_sr03_messages_create.sql` 4. `devoir_sr03_messages_insert.sql` - Les fichiers de configuration sont dans `site-web/config`. On y trouve notamment : - `database.ini` contenant les identifiants de connexion à notre BDD - `mail.ini` contenant les identifiants de connexion au serveur mail en ligne **Mailo** - `secrets.ini` contenant le poivre utilisé dans le hachage des mots de passe - `mot_de_passe_users_en_clair.md` pour se connecter à l'application - `rapport.md`, qui est ce même rapport ## Introduction : Quand on parle de sécurité des applications, cela concerne tous les moyens mis en place pour rendre l'applicaiton résiliente aux différentes attaques possibles, qu'elles soient passives ou actives. Le terme passif renvoyant aux menaces de type : copie ou écoute d'information illégale. La sécurité est donc devenue un point essentiel de nos jours. En effet une entreprise, qu'importe sa taille, doit prendre conscience qu'elle est vulnérable à la cybercriminalité. Les conséquences d'une telle attaque peuvent être catastrophique. Si des dommages sont causés cela peut demander beaucoup de temps et d'argent pour réparer les dégâts. De plus, certaines applications peuvent utiliser les données des clients afin de les revendre sur le marché noir par exemple. Mais quelles sont les techniques à employer pour sécuriser une application ? Pour répondre à cette question, nous avons utilisé plusieurs moyens : - Un tableau récapitulant les failles corrigées, et très sommairement comment nous les avons bouchées - Une liste de bonnes pratiques pour la sécurisation d'une application, qui explique en détail les techniques employées pour protéger notre application de banque. Plus complet que le tableau précédent. - La question de synthèse effectuée sur le thème du hachage ## 1. Tableau des failles identifiées et correction Faille | Corrections mises en place ------ | -------------------------- Injections **SQL** sur les requêtes avec saisies utilisateur | Utilisation systématique de requêtes paramétrées **Authentification** | Ajout de captchas, de messages d'erreurs non explicites, et de la double authentification par jeton expirable reçu par mail **XSS** virement et message | Utilisation de `htmlspecialchars()` pour échapper les caractères malicieux Protection supplémentaire **XSS** | Utilisation de `ini_set( 'session.cookie_httponly', 1 );` et d'autrs directives pour ne traiter qu'avec un cookie de session HTTPOnly **CDS** | Vérification de la session et redirection vers page d'authentification si non connecté, déconnexion automatique après 10 minutes d'inactivité. Contrôle du mot de passe lors d'un virement. **CSRF** Virement | Ajout d'un jeton unique dans le formulaire, contrôlé lors de l'envoi **RDNS** `myController.php?action=listMessages&userid=XXX` | L'`userId` est passé en session Mots de passe, cookies de session, données de formulaire, headers, etc. transitent **en clair** | Mettre en place une connexion HTTPS et désactiver le HTTP Mot de passe stocké **en clair** dans la BDD | Hachage, salage et poivrage du mot de passe, voir la question de synthèse **Attaque aléatoire** login / mdp | Blocage après 3 tentatives d'authentification successives ratées, et utilisation de captchas Pas de contrôle des champs **envoyés** par le client | Tout les champs sont contrôlés à toutes les étapes. Des messages d'erreurs adéquats s'affichent lorsqu'un formulaire est mal rempli Pas de **contrôle de droit d'utilisateur** | Contraintes évoquées dans le sujet respectées. Des contrôles sont effectuées sur les autorisations de l'utilisateur lors du traitement des formulaires. Fichiers exposés par **HTTP** | Introduction d'un fichier .htaccess à la racine de notre site, et dans les sous-dossiers pour restreindre l'accès uniquement aux fichiers nécessaires. Directive `Options -Indexes` pour supprimer la navigation dans l'arborescence. ## 2. Liste des bonnes pratiques Dans cette partie nous allons développer comment nous avons fait pour détecter les failles et sécuriser l'application. ### Utilisation des failles connues Certaines failles sont connues pour être régulièrement utilisées lors d'attaque. Puisqu'elles sont connues, on peut également "facilement les corriger". En effet, même si on ne s'y connait pas trop on peut trouver des solutions assez rapidement sur internet, ces sujets étant très récurrement traitées en ligne. De plus les langages de programmation intègrent souvent des fonctions toutes prêtes pour corriger certaines de ces failles. Par exemple pour le hachage de mots de passe dans notre base de données (ne plus avoir les mots de passes stocker en claire) nous avons utilisé des fonctions de PHP. ( `password_hash()` ou `crypt()`) Il existe une dizaine de types de vulnérabilité que l'on retrouve régulièrement : - Injection (~40%) - Violation de gestion d’authentification - Violation de gestion de session - Cross-Site Scripting (XSS) (~30%) - Violation de contrôle d’accès - Mauvaise configuration de sécurité - Exposition de données sensibles (~15%) - Falsification de requête intersites (CSRF) - Utilisation de composants avec des vulnérabilités connues - Redirections et renvois non validés Il est donc très utile de vérifier que notre application ne comporte pas ses failles et donc de les corriger. ### Contrôle des données envoyées et reçues Les injections et XSS sont les failles les plus courantes. Elles consistent à envoyer une donnée non fiable à un interpréteur en tant qu'élément de commande. Cela permet de faire exécuter des commandes au système (injections PHP), à la base de donnée (injection SQL), etc. Un pirate peut ainsi d'accéder à des données non autorisées ou utiliser ces informations pour par exemple se connecter à l'application sans identifiants. Pour éviter ce genre de problème nous avons détecté tous les endroits ou il est demandé de rentrer du texte et/ou des valeurs par l'utilisateur. - Toutes les requêtes SQL sont paramétrées. - Lorsqu'un texte saisiepar l'utilisateur doit être affiché à l'écran, on utilise la fonction PHP `htmlspecialchars()` afin d'échapper tous les caractères HTML et Javascript. - Toutes les données saisies par l'utilisateur sont vérifiées individuellement avant d'être traitées. Un message d'erreur est renvoyé si une donnée est incorrecte #### HTTPS Il faut pouvoir protéger toutes les données échangées entre le client et le serveur. Sinon, il ne sert à rien de par exemple hacher le mot de passe, puisque le mot de passe en clair pourrait être écouté sur le réseau. De même pour les virements effectués, les messages envoyés, etc. Le HTTP (hyperText Transfer Protocol) permet cet échange mais n’importe qui peut l'écouter. Cela ne pose pas trop de problème si on est dans le cas de la lecture d’un article web. Mais dans le cas d’une application de banque en ligne comme la nôtre cela pose des soucis. C’est à ce moment que le protocole HTTPS rentre en jeu. Ce protocole utilise des algorithmes cryptographiques tels que SSL, ou son remplaçant TLS pour sécuriser les échanges entre le client et le serveur. On parle indifféremment de certificat SSL ou TLS, mais il faut savoir que le protocole SSL n’est plus d’actualité depuis qu’il a été remplacé par le TLS, une version plus sûre basée sur le même principe. Ce certificat électronique s’applique au site pour sécuriser les échanges de données en assurant leur chiffrement à l’aide d’une clé de cryptage asymétrique. Un site protégé par un certificat SSL (ou TLS) affiche le fameux cadenas prouvant que la communication est sécurisée. Il existe différents types de certificats: - Le certificat SSL gratuit (type Let’s Encrypt) - Le certificat à validation étendue (Extended SSL) - Le certificat à validation de l’organisation (Organization SSL) - Le certificat à validation de domaine (Domain SSL) - Le certificat multi-domaine (WildCard) Ces certificats peuvent être gratuits, comme payant, et sont délivrés par des organismes spécifiques. Dans notre projet, nous n'avons pas implémenté le HTTPS car il serait difficile de déployer un certificat, et que vous puissiez ensuite l'utiliser à travers notre dépot gitlab. Cependant, il serait absolument crucial de mettre un place un tel certificat afin de sécuriser tous les échanges entre un client, et le serveur d'application dans un contexte de production. Dans le cas contraire, de nombreuses autres corrections de failles n'auraient aucun effet. ### Gestion des mots de passe Certaines données sensibles comme les mots de passe ont besoin d'être stockés pour l'identification. Si l'on stocke ces informations dans une base de données en clair, alors n'importe qui accèdant à cette base de données (hacker, hôte de la base de données ou propriétaire de l'application) peut directement visualiser les mots de passe. Pour empêcher cela et protéger les utilisateurs, nous avons utilisé le hachage (avec ARGON2_ID), avec sel et poivre. Cette technique permet de créer une empreinte numérique à partir du mot de passe et donc de stocker dans la base de données uniquement cette empreinte. Le processus inverse n'est théoriquement pas faisable. Plus de détails à propos de ce procédé sont expliqués à la fin du rapport, dans la question de synthèse. Pour notre application, le poivre se trouver dans le fichier `/config/secrets.ini`. On peut générer un mot de passe salé et poivré directement grâce à la fonction ` getHashedSaltedPepperedPassword` du fichier /model/securityModel.php : ``` PHP function getHashedSaltedPepperedPassword(string $plainPassword) { $pwd_peppered = hash_hmac('sha256', $plainPassword, getPepper()); return password_hash($pwd_peppered, PASSWORD_ARGON2ID); } ``` La vérification du mot de passe est assurée dans notre application par `verifyHashedSaltedPepperedPassword(string $plainPassword, string $hashedPassword)`. Cette fonction permet de vérifier qu'un mot de passe en clair est bien le même que la version hachée, salée, et poivrée du mot de passe. On peut ainsi comparer le mot de passe de l'utilisateur saisi en clair lors de l'authentification, avec le mot de passe haché, salé, et poivré stocké en BDD. ### Gestion de sessions Pour éviter que des personnes mal intentionnées puissent utiliser la session d'un autre utilisateur sans autorisation, nous avons ajouter l'expiration automatique de la session. Cela peut être utile dans plusieurs cas. Par exemple, si vous quittez votre poste pour la pause de midi sans verrouiller votre ordinateur. Quelqu'un peut alors tenter d'utiliser votre session ouverte sur votre ordinateur. Seulement, votre session aura expirée automatiquement, après 10 minutes d'inactivité sur le site. L'utilisateur ne pourra donc rien faire s'il arrive 10 minutes après que vous soyez parti, car vous serez déconnecté automatiquement. Au niveau technique, il suffit d'ajouter, en haut d'une page à protéger, l'inclusion du fichier suivant : ``` php require __DIR__ . '/utils/automaticLogoutHandler.php'; ``` Le fonctionnement est simple : à chaque requête sur la page, on compare la dernière date d'accès (enregistrée en session) avec l'heure actuelle. Si l'intervalle de temps est trop grand, alors on appelle le controlleur de déconnexion qui se charge de déconnecter l'utilisateur (sans redirection, donc sans détournement possible pour l'utilisateur). La durée d'expiraiton de la session est à étudier au cas par cas mais pour des applications sensibles comme notre banque en ligne il est largement préférable de mettre un intervalle de temps court, et de laisser l’utilisateur se reconnecter plutôt que de laisser de longues sessions. On retrouve dans le fichier `/controller/utils/automaticLogoutHandler` : ``` PHP if(isset($_SESSION["lastConnectionTimeStamp"])) { if ((strtotime("now") - $_SESSION["lastConnectionTimeStamp"]) > 600) { $automaticDisconnection = TRUE; require __DIR__ . '/../disconnectionController.php'; exit(); } } ``` La gestion de session concerne également les fonctions importantes de l'application, comme les virements par exemple. En effet, il faut pouvoir empêcher l'exécution d'une requête CRSF par un client dupée. Pour pallier à ce problème on peut utiliser des jetons. Ce « jeton » est placé de manière cachée à chaque demande du formulaire. Le serveur ne traitera le formulaire que si le jeton reçu est bien le même qu'il a émis. De ce fait, on évite les attaques CSRF, car la valeur du jeton n'est pas prédictible. Nous avons choisi de protéger la fonction **Virement** avec un jeton pour éviter les attaques CSRF sur cette dernière. Une deuxième manière est de redemander le mot de passe de l'utilisateur pour être certain que le formulaire ait bien été envoyé intentionnellement par ce dernier. La fonction **Virement** est également protégée de cette manière. ### Authentification rigide + 2FA Nous voulions atteindre plusieurs buts pour notre authentification : - Pas d'injections SQL possible (voir au-dessus) - Impossible de faire une attaque de force brute avec login / mot de passe - Impossible de savoir si un utilisateur existe ou non - Second facteur d'authentification obligatoire, avec expiration après de 5 minutes - Blocage automatique après 3 tentatives d'authentifications successivement ratées Avec ce cahier des charges, l'authentification est la partie la plus avancée de notre projet en terme de sécurité. L'authentification se fait en plusieurs étapes : 1. Rentrer son login et son mot de passe 2. Faire le captcha 3. Si le captcha est invalide, retour à 1. Sinon, saisir le jeton reçu par mail (mail = login) 5. Faire le captcha 6. Si le captcha est invalide, retour à 1. Sinon, si le login, le mot de passe, et le jeton sont valides, alors l'utilisateur est connecté. Sinon rediriger sur la page d'authenfification **/!\ Pour plus de facilité pédagogique, le jeton 2FA est également affiché dans la console PHP afin que vous puissiez facilement vous connecter. Ce ne serait naturellement pas le cas en production** #### Protections anti force brute Pour éviter que quelqu'un ne puisse spammer les tentatives d'authentifications dans le but de trouver le mot de passe et le login de quelqu'un, nous avons ajouté deux couches de sécurité : - Un compteur de connexion successive ratée est implémentée, avec blocage après 3 tentatives. Lorsque l'utilisateur tente de se connecter, il doit alors attendre 1 minute après la dernière tentative ratée(le compteur de temps restant est affiché sur la page). Ce compteur fonctionne grâce aux données enregistrées en session, il est donc possible de l'outrepasser en supprimant son cookie de session à chaque tentative. Cependant, cela devrait suffire pour bloquer la majorité des utilisateurs lambdas. Mais pour les pirates, cela ne fonctionnerait pas. - Nous avons donc ajouté des captchas obligatoires (fournis par hCaptcha) lors de la saisie du login / mot de passe, et lors de la saisie du jeton reçu par mail. Ces jetons sont vérifiées avant toute autre saisie. Cela enlève tout espoir de brute-force automatisée (même si des services de résolution de captcha existent, la résolution prend toujours environ 10s par captcha avec ce genre de service) - Même si le login saisi n'existe pas, la page demandant de rentrer le jeton reçu par mail s'affiche tout de même. Le pirate ne peut donc pas savoir si le login qu'il a saisi est réellement celui d'un utilisateur. Si le login n'existe pas, le jeton 2FA n'est pas généré et le pirate ne peut donc pas continuer l'authentification, même si la page s'affiche. - Dans le cas ou le les captchas sont corrects, et le jeton 2FA est correct, mais que le mot de passe est incorrect, le message "Login ou mot de passe incorrect" s'affiche. Encore une fois, un pirate ne pourrait donc pas savoir si le login qu'il a saisi existe réellement en BDD. #### Le Captcha Le captcha utilise le principe du test de Turing mais inversé. Dans le test de turing on met en relation un humain d’un côté et de l’autre soit un autre humain soit un ordinateur. Si la personne n’arrive pas à savoir si elle parle à un humain ou non le test est validé. Dans notre cas le Captcha va justement essayer de savoir s’il a en face de lui un humain ou non. Il existe différents types de captcha. Le captcha à deux mots, où on demande à l’utilisateur de rentrer les deux mots à l’écran. A noter qu’un seul des deux mots est connu le deuxième est inconnu. Une fois qu’un certain nombre d’utilisateur ont répondu la même chose pour ce deuxième mot il est alors ajouté au dictionnaire. Deuxièmement nous avons un captcha développé par google « je ne suis pas un robot » ou il suffit de cliquer sur une case. Il en existe aussi ou il faut identifier des images, reconstituer des puzzle etc… Pour notre application nous utilisons un captcha par identification d’image fournis par hCaptcha. Nous l'avons choisi car contrairement à reCaptcha, il respecte la confidentialité des utilisateurs. Pour utiliser ce captcha il faut en premier inclure la balise : ``` PHP <script src="https://hcaptcha.com/1/api.js" async defer></script> ``` La vérification du captcha se fait dans la fonction `verifyCaptcha( string $captchaReponse)` du fichier `/model/securityModel.php`. ``` PHP function verifyCaptcha(string $captchaResponse) { $data = array( 'secret' => "0x2Db9AB2177D8a54046872896804A013116C76BEb", 'response' => $captchaResponse ); $verify = curl_init(); curl_setopt($verify, CURLOPT_URL, "https://hcaptcha.com/siteverify"); curl_setopt($verify, CURLOPT_POST, true); curl_setopt($verify, CURLOPT_POSTFIELDS, http_build_query($data)); curl_setopt($verify, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($verify); $responseKeys = json_decode($response, true); if ($responseKeys["success"]) { return TRUE; } else { return FALSE; } } ``` #### Le mail contenant le jeton Pour l'envoi du mail contenant le jeton d'authentification, nous avons utilisé la librairie `PHPMailer`, qui permet de se connecter en SMTP à n'importe quel serveur local ou distant. Nous avons créé une adresse mail `sr03@mailo.com`, hébergé chez mailo. A chaque tentative de connexion, les méthodes contenues dans notre modèle `mailModel.php` permettent de se connecter au serveur SMTP de manière sécurisée, et d'envoyer le mail avec le jeton d'authentification unique. Ce mail n'est bien sûr envoyé que si le login saisi correspond bien à un utilisateur enregistré. Le jeton expire au bout de 5 minutes. Voici un exemple du mail : ![](https://i.imgur.com/B1af7HD.png) ### Séparer les différents usagers Une fois connectés il est important de pouvoir distinguer les utilisateurs pour savoir qui a accès à quoi. En effet il ne faudrait pas qu’un utilisateur classique puisse consulter le profil d’autres utilisateurs dans le cas de notre application. On distingue 2 types d'usagers : les clients, et les employés. Il faut donc penser à mettre des vérifications dans le code. Toutes les actions effectuées par le client sont contrôlées côté serveur. Si l'utilisateur n'a pas l'autorisation nécessaire (par exemple un client qui fait un virement depuis le compte d'un autre), alors un message d'erreur s'affiche. Un point d'importance a été mis sur les différents messages permettant d'avertir l'utilisateur du résultat de ses actions. Toutes les contraintes d'autorisations spécifiées dans le sujet ont été implémentées. ### Protection des cookies Pour rappel, un cookie est un petit ensemble de données que l'on stocke côté client. Il existe des cookie de session. Par défaut, ils sont supprimées lorsque l'on ferme son navigateur. Il existe aussi des cookies permanents qui vont perdurer même une fois le navigateur fermé. Ces cookies sont sensible aux attaques de type XSS, et aux aspirateurs à cookies. Il existe un moyen assez simple de s'en protéger. En effet on peut utiliser la directive `HTTPOnly`. Cela va rendre les cookies inaccessible aux scripts et vont être envoyés uniquement au serveur. Quand à `session.use_only_cookies` elle va interdir les cookies de session via l'url. On évite également l'affichage des erreurs serveurs dans les pages envoyées aux clients avec `display_errors` à 0 : ``` PHP ini_set('display_errors', '0'); ini_set('session.cookie_httponly', '1'); ini_set('session.use_only_cookies', '1'); ``` Ces trois lignes sont placées avant chaque démarrage de session : `session_start()`. Il n'est pas nécessaire de les inclure si elles sont déja présentes dans le fichier `php.ini` ### Protection des répertoires Il ne faut pas qu'un pirate puisse accéder à l'arborescence de notre programe. Il pourrait alors consulter des pages qui ne lui sont pas destinées, découvrir l'architecture de l'application, et lire des fichiers de configuration cruciaux. De plus il faut pouvoir protéger ces fichiers et n'autoriser les requêtes demandant qu'un ensemble de ressources précises. Pour ce faire il faut créer un, ou plusieurs fichiers **.htaccess**, qui permettent d'autoriser ou de refuser l'accès à certaines ressources. Ce n'est pas nécessaire si la configuration est réalisée dans `php.ini` : ``` hacess Options -Indexes Require all denied ``` Ces quelques lignes dans le fichier vont rendre l'accès impossible à tous les fichiers pour tous les utilisateur. L'arborescence est également désactivé. Si quelqu'un requête un des fichiers du dossier il obtiendrait: ![](https://i.imgur.com/ds0FSxb.png) Mais ce fichier peut aussi permettre d'effectuer des redirection en cas d'erreur, ou seulement certains utilisateur d'avoir accès à certains fichier. ``` hacess ErrorDocument 404 /index.php ErrorDocument 404 http://google.fr ErrorDocument 410 /index.php ErrorDocument 410 http://google.fr ``` Permet de rediriger l'utilisateur vers une page google si il optient une erreur 404/410. On retrouve souvent la partie admin d'une application en ajoutant admin à la fin de l'URL. Ex `http://localhost/sr03-td-securite/site-web/admin`. Il est donc important de protéger ces fichier car une personne s'y connaissant un peu aura vite fait de les trouver. Dans notre projet, nous n'avons autorisé que les requêtes vers : - `index.php` - `controller/*` ## Pour aller plus loin Nous avons ajouté deux autres bonnes pratiques mais que nous n'avons pas utiliser. En effet notre application étant en place juste le temps du projet il est inutile de mettre à jour (déjà a jour) de même pour les sauvegardes. ### Bien configurer et masquer les composants de l'application On retrouve dans chaque système d'exploitation des vulnérabilités. Une fois détectés, elles sont souvent rapidement corrigées par l'éditeur par d'une mise à jour. Une fois que la vulnérabilité est connue, n'importe quel cybercriminel peut l'utiliser. Cela peut poser problème si le logiciel utilisé n'est pas à jour. C’est pour cela qu’il est aussi important de cacher à l’utilisateur la version utilisée. Si il ne connaît pas la version du serveur web par exemple, il sera plus difficile pour lui de trouver les failles. Encore mieux si le nom du serveur web / du langage de programmation est masqué. Pour notre application, nous avons modifié la configuration Apache pour désactiver la version dans les headers, grâce à : ``` txt # Désactive les headears de apache ServerSignature Off ServerTokens Prod ``` Et supprimé le header PHP contenant PHP + la version avec : ``` expose_php = Off ``` Vous ne pourrez cependant pas le voir car cette configuration dépend de votre installation de Apache et de PHP. Pour aller plus loin et masquer totalement le fait que nous utilisons PHP, nous aurions pu changer le nom du cookie `PHPSESSID` mais nous avons considéré que les modifications précédentes étaients déjà suffisantes. Pour finir il peut être très utile de désactiver les fonctionnalités (modules Apache + PHP, phpMyAdmin) non utilisées, afin de réduire la surface d'attaque. ### Effectuer des sauvegardes régulières Une attaque peut avoir pour but d'endommager un système informatique. Il est donc très utile d'avoir des sauvegardes régulières. De nombreuses solution existent (disque dur, cloud). Mais la plus sur reste encore l'utilisation de Git. Pour finir il peut aussi être intéressant pour les sauvegardes de Base de données par exemple de les crypter. Réduisant ainsi les risques au cas ou ces sauvegardes seraient exposées. ## Organisation du code Deuxièmement il faut être rigoureux dans la création de l'application. Si l'on travaille sur un même projet à plusieurs, une mauvaise gestion en plus d'entrainer des difficultés à coder entrainera des difficultés dans la sécurisation. Il est beaucoup plus difficile de détecter ou de corriger des failles si le code est incompréhensible. En outre, sur le long terme, le créateur ne serez pas forcément toujours celui qui maintiendra le code en place. Il faut donc faire quelque chose de propre dès le départ. . Il est donc nécessaire de **bien gérer ses composant**, et d'utiliser par exemple **git** pour la gestion du code source. ### Programmation modulaire et MVC Répartir en module est très intéressant à plusieurs niveaux. Au-delà du fait qu'elle permet un développement facilité (chaque personne peut travailler sur un module), une taille réduite du code source et une meilleure visibilité. Ce qui nous intéresse surtout c'est une meilleure structuration et une meilleure maintenabilité du programme. On doit plus gérer un code dans son ensemble mais des composants. L’application de banque en ligne a été entièrement réécrité de manière modulaire, en utilisant un modèle `MVC` le plus possible. L'arborescence du projet respecte ce modèle avec `model/`, `controller/` et `view/`. Chaque fonction (écrire un message, virement, fiche client, etc.) a été implémenté au sein d'un module. Un module peut ensuite être placé au sein d'une page web pour être utilisé. Page web et modules sont donc décorrélés. Cela nous a permis de garder exactement le même front-end sur l'application de banque en ligne. Toutes les fonctions principales (hors messagerie) se retrouvent sur la page d'accueil, et non dans des pages séparées. Toutes les actions des utilisateurs connectées sont traitées par le controlleur `accountController.php`. Les modules sont placés dans `/view/module/`, et le fichier permettant de les gérer est `/view/moduleManager.php`. La programmation modulaire permet également de placer un même module dans plusieurs pages web différentes. Nous avons pu placer le module d'écriture de message dans la page d'accueil, et dans la page "Messagerie", sans duplication de code. ## 3. Question de synthèse : une technique de sécurité web, le hachage Il est dangereux de stocker les mots de passes en clair dans une base de données. En effet une fois qu'un utilisateur (autorisé ou non) a accès à cette base, il peut accéder à tous les comptes utilisateurs car il peut voir leur mots de passe. Pour contrecarrer ce problème on utilise une fonction de hachage sur le mot de passe. ### En quoi consiste le hachage ? En informatique, une fonction de hachage prend des blocs de données (ou un flux) en entrée et en produit une empreinte unique de taille fixe (assez courte, usuellement entre 128 et 512 bits en fonction de l'algorithme employé). Ce qui en fait tout son intérêt est sa rapidité de calcul (ou sa lenteur), et qu'il est théoriquement impossible de retrouver le contenu à l'origine de l'empreinte. Un même contenu produira toujours exactement le même hash, mais une infime variation produira un hash totalement différent. ### Comment hasher un mot de passe ? #### Niveau 1: Hash simple Le premier niveau de hachage est assez simple. On peut utiliser des algorithmes tels que `sha256` pour retourner notre mot de passe haché. Il faut veiller à ne pas utiliser d'algorithmes obsolètes tels que `md5` ou `sha1`. Ensuite il suffit de ne stocker que ce hash en BDD. Avec ce hachage, on limite vaguement le risque mais on ne l'élimine pas du tout. En effet, si plusieurs utilisateurs ont des mots de passes similaires, le hash sera le même. De plus, un pirate peut utiliser une rainbow table (table de correspondance 'chaine' -> hash) afin de retrouver les mots de passes les plus communs en une fraction de seconde. Il existe en ligne de nombreux dictionnaires contenant les listes de mots de passe les plus utilisés(rockyou par exemple), qui s'avèrent également redoutables contre un simple hachage du mot de passe. #### Niveau 2: Hash (choisi) + Salt Pour contrer ce processus d'attaque par rainbow table, un deuxième niveau de hachage a été trouvé. On ajoute un salt unique, créé aléatoirement, à notre mot de passe avant de le hasher. Ce sel est stocké à côté du mot de passe en base de données. Enfin, deux mots de passe semblables auront un hash différents puisque le sel ajouté est différent. Cela rend obsolète l'attaque par rainbow table, car il faudrait recalculer toute la table pour chaque sel, afin de pouvoir réaliser l'attaque. De plus, on peut utiliser des algorithmes de hachage spécialement prévus pour être lents à calculer (bcrypt, argon2_id, ...). Grâce à ces algorithmes, le calcul d'un hash relève de la dizaine ou de la centaine de milisecondes, ce qui réduit amplement l'efficacité d'une attaque par force brute, et par dictionnaire. Cependant, les mots de passes triviaux, comme "1234" (disponibles dans notre BDD du projet) peuvent toujours être trouvés relativement rapidement avec des attaques par dictionnaire bien choisis. En PHP, on peut utiliser les fonctions : `crypt()` et `password_hash()`. La valeur retournée inclura automatiquement le salt comme partie intégrante du hash. Il suffit ensuite de stocker la valeur retournée en BDD. Pour la vérification du mot de passe on peut alors utiliser les fonctions `crypt()` et `password_verify()`, afin de vérifier automatiquement qu'un mot de passe en clair correspond bien à un même mot de passe salé et haché. Retour de la fonction password_hash() : ![](https://i.imgur.com/0SIwwZ4.png) #### Niveau 3: Hash + Salt + Pepper = Tartare Les mots de passe très faibles protégés par le niveau précédent restent sensibles aux attaques par dictionnaire. On peut rendre ce système encore plus résistant, en concaténant une autre clé (en plus du sel) avant hachage, appelée pepper. Cette clé est privée, ne doit pas être stocké dans la BDD, et doit être la même pour tous les mots de passe. Cette clé souvent appelé pepper rend l'attaque par dictionnaire inutilisable, car même si le mot de passe de l'utilisateur est très faible, le pepper étant lui-même très fort, l'attaque ne pourra pas réussir. Il faudrait tout d'abord que le pirate réussisse à trouver le pepper. Ainsi, même les mots de passe les plus faibles sont protégés. Il faut cependant que le pepper soit lui-même fort, car sinon il est inutile et sera trouvée lors d'attaques par dictionnaire. Le pepper doit cependant être gardée secrètement et ne doit pas être divulgé, auquel cas il devient inutile. S'il est perdu, toutes les données deviennent inutilisables. Il y a donc une grande responsabilité quant à la gestion de ce pepper. Pour le projet nous avons choisi de hacher, saler, et poivrer les mots de passe avant stockage, avec l'algorithme `sha256` pour l'ajout du poivre, et `ARGON2_ID` pour le salage et hachage. Voir `model/securityModel.php` Vous pourrez trouver, à but pédagogique, un fichier avec les mots de passes en clair (`mot_de_passe_users_en_clair.md `) de chaque utilisateur, vous permettant ainsi de vous connecter à la base de données. La page de création de compte n'étant pas demandée, les utilisateurs sont rentrés en dur dans la base de données grầce à un script SQL.

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully