> Exit 0;

Le blog d'un développeur qui de 0 devient un 1.

Web, sécurité et Laravel : exemples et cas d'usage [1/3] image

SÉCURITÉ

Web, sécurité et Laravel : exemples et cas d'usage [1/3]

Par Aubin Puyoou, publié le 14/09/2021 à 19:13.

De manière à illustrer les différentes fonctionnalités de sécurité mises à disposition par le framework, voici quelques exemples typiques de failles connues et de leurs applications.

Environnement de test

De façon à fournir quelques exemples, je me suis muni d'une image Docker disponible gratuitement sur le DockerHub, la Damn Vulnerable Web Application.

Si vous souhaitez tester chez vous :

docker run --rm -it -p 80:80 vulnerables/web-dvwa

Cette application déployée sur le conteneur, est destinée à faire découvrir les plus courantes failles de sécurité, en nous donnant la possibilité de les tester directement.

Je sélectionnerai donc ici pour mes tests certaines de ses fonctionnalités de manière à illustrer les protections directement fournies par Laravel.

Injections SQL

L'injection SQL est une faille de sécurité permettant de détourner l'usage d'une requête utilisateur, de manière à récupérer d'autres informations, différentes de celles préconçues au fonctionnement initial de l'application. Ce type de faille peut donner accès à des informations propres au serveur de l'application, mais peut également permettre de récupérer des mots de passe, des données de facturation, etc... Un exemple basique est donné ci-dessous.

Exemples

Utilisation Normale

Prenons notre DVWA, menu "SQL injection" et testons notre interface. Un champ "User ID" nous invite à saisir un identifiant utilisateur. Le résultat obtenu nous donne ici les informations associées à l'utilisateur correspondant.

Utilisation Normale

Mais la machine présentée ici étant vulnérable, nous pouvons facilement nous imiscer à l'intérieur de la base.

En injectant du code

En injectant du code

Ainsi, en manipulant la balise input mise à disposition, nous pouvons facilement injecter une surcouche de SQL et ainsi par exemple récupérer les hash des mots de passe de tous les utilisateurs listés dans l'application.

4' UNION SELECT first_name, password FROM users; #

Via cette expression, je rajoute des données à récupérer via la requête initialement prévue qui se retrouve transformée en :

SELECT first_name, surname FROM users WHERE id='4'
  UNION SELECT first_name, password FROM users; #'

Ici, la base est tout de même protégée par une limitation des droits de notre utilisateur, mais quelques manipulations supplémentaires auraient peut être pu nous permettre de changer de compte et d'ainsi escalader, de façon à pouvoir mettre un peu plus de bazar.

Protections offertes par le framework

Les outils de gestion de bases de données présentés dans l'article précédent incluent directement des protections contre ce type d'attaque. L'ORM Eloquent permettant de manipuler des objets, le champ d'application de telles requêtes forcées se retrouve ainsi fortement limité. D'autre part, les autres méthodes associée à la facade DB incluent des fonctionnalités de préparation de requête avec nettoyage des chaînes. Ainsi, notre bloc d'injection se serait retrouvé inclut dans le paramètre envoyé au moteur SQL, et celui-ci n'aurait retourné aucun résultat.

Cependant il faudra se montrer vigilant quand à la bonne utilisation des méthodes classiques, DB::raw(), DB::selectRaw(), etc... et contrôler systématiquement les champs sélectionnés en typant correctement ou en nettoyant les chaînes de leurs caractères spéciaux, envoyées en paramètres au moteur de base de données.

Cross-Site Request Forgery (CSRF)

Le Cross-Site Request Forgery est un type d'attaque permettant à un attaquant d'envoyer une requête HTTP vers un site de manière indirecte, au travers d'une session utilisateur lambda. Ainsi, suivant la configuration d'un système d'authentification, il est possible pour quelqu'un connaissant le site de forcer l'exécution de certaines requêtes : changement de mots de passe, suppression de profil, transfert de fonds... Un exemple typique.

Exemples

Schématisons

Prenons l'exemple de Célestin. Un samedi après-midi, il se connecte sur le site de sa banque, mais malheureusement, Célestin conserve son argent chez une qui a pris la décision de faire quelques coupes budgétaires sur leur sécurité informatique. Célestin veut vérifier le solde de son compte.

  • Célestin se connecte. Il vérifie son solde, voit qu'il lui reste quelques centaines d'euros pour le mois, mais ne se déconnecte pas
  • A ce moment là, Célestin reçoit un mail de promotion Amazon, qui s'avère être du phishing, et clique sur le lien promotionnel
  • La page s'ouvre mais affiche un logo d'image cassée, comme si le lien était introuvable
  • Célestin vient de perdre les accès à son compte bancaire, car la requête envoyée pour récupérer l'image a en fait modifié son mot de passe

Par la pratique

Changement de mot de passe

Prenons notre DVWA, menu "CSRF". Nous nous retrouvons face à un formulaire de changement de mot de passe. En modifiant le mot de passe, on peut s'apercevoir dans notre URL que les paramètres sont passés en clair (Cf. code exécuté ci-dessous), et qu'à aucun moment ne nous est redemandé une quelconque authentification.

Changement de mot de passe

Notons ici que la session en cours comporte les Cookies suivant, car ce type d'attaque va se servir de ceux-ci pour se faire passer pour nous :

  • PHPSESSID : pour identifier la session utilisateur
  • XSRF-TOKEN : pour identifier la page en cours, et valider l'authenticité de la page côté serveur

Ci-dessous, un simple code HTML exécutant une requête GET vers le serveur cible, par le biais d'une image.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </head>
    <body class="home">
    <img src="http://localhost/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#">
    </body>
  </html>

Toute personne ouvrant ce fichier HTML, sur le même navigateur et avec son compte authentifié sur le site verra son mot de passe modifié en "password". Les cookies sont disponibles universellement, peu importe que vous changiez d'onglet, si une requête provient de votre navigateur ils seront utilisés de la même façon. Ainsi sont partagés les jetons de session, d'expiration etc...
Cet exemple ne présente qu'une faille associée à une requête GET, mais il est facilement possible de simuler des validations de formulaires plus complexes à l'aide de Javascript.
A noter que ce type d'attaque peut également atteindre un réseau interne si votre machine y est connecté.

Protections des formulaires par le framework

La documentation décrit les méthodes mises en place pour palier à ce type de faille.

Un jeton @csrf est à insérer à l'intérieur de chacun des formulaires, de manière à confirmer la validité de la saisie.

Ce champ insère une balise "input" cachée, qui contient notre jeton, et qui sera envoyé en même temps que tous les autre paramètres. Dans le cas contraire, Laravel renvoie une erreur 419 qui lui est propre et qui caractérise ce type d'erreur.
Cette protection est désactivable, mais veillez donc à protéger correctement vos routes et à sélectionner précautionneusement les routes exemptées de ces validations.

Je n'ai détaillé dans cette partie que l'utilisation du jeton pour des applications développées entièrement avec Laravel, mais il faut savoir que d'autres sécurités sont mises en place dans le cas d'application manipulant des frameworks Javascript.

En résumé

Cette première partie présentait deux des plus grosses failles connues et exploitées à ce jour. L'outil moderne qu'est Laravel met à disposition des sécurités dont nous ne pouvons pas nous passer, et qui sont utilisables facilement lors d'ajout de nouvelles fonctionnalités. Tâchons de ne pas passer à côté.