Dans cette série consacrée à la sécurité des applications web, nous allons nous pencher sur un type d'attaque particulièrement efficace : l'attaque par token grab.
Qu'est ce que le token grab ?
Le principe est simple : on vole les cookies ou les données du localStorage d’un navigateur. Ces données sont utilisées pour maintenir une session ouverte et donc, une fois dérobées, permettent à un attaquant de prendre le contrôle d’un compte sans avoir à se reconnecter (passant ainsi au dessus des systèmes de sécurité comme l'authentification à double facteur).
Imaginons un exemple concret : vous recevez un exécutable que vous lancez sans faire attention. En arrière-plan, ce fichier va extraire vos cookies et les envoyer à l’attaquant. Celui-ci les injecte dans son propre navigateur, et hop ! Il est connecté sur vos comptes.
Qui est responsable ?
Les plus perspicaces d'entre vous pourraient objecter que contrairement aux autres attaques comme les injections SQL, celle-ci ne provient pas directement de nous, développeurs. En effet, c'est l'utilisateur qui a commis l'erreur d'exécuter un programme qu'il n'aurait pas dû.
Le problème est que les conséquences vont directement impacter votre site. C'est votre support que la victime va contacter pour restaurer ses données. De plus, l'utilisateur ne saura pas forcément qu'il s'est fait attaquer par ce biais là et pensera que la faute provient de votre site. C'est pourquoi il est crucial de mettre en place des contre-mesures pour protéger nos utilisateurs.
Contre-mesures
Cookie de session et SessionStorage
La première ligne de défense consiste à faire attention au type de cookies / stockage que vous utilisez. Il existe deux catégories principales :
-
Cookies de session
Ces cookies sont sauvegardés dans la mémoire du navigateur et sont automatiquement supprimés lorsque l'utilisateur ferme son navigateur. Étant stockés en mémoire, ils sont plus difficiles d'accès depuis l'extérieur. -
Cookies persistants
Ces cookies sont sauvegardés dans une base de données SQLite facilement accessible par un attaquant (cette base est chiffrée dans certain cas mais utilise une clef qui est récupérable).
Les données en session sont donc plus sécurisées mais ne sont pas idéales d'un point de vu expérience utilisateur car il force la personne à se reconnecter à chaque fois qu'il ferme son navigateur. Cependant, pour des sites gérant des données très sensibles (sites bancaires, hébergement, gestion de noms de domaine), il peut être pertinent de privilégier la sécurité. Ces sites n'ont d'ailleurs pas forcément besoin que l'utilisateur reste connecté H24.
La re-authentification
Malheureusement, dans de nombreux cas, l'utilisateur s'attend à rester connecté. Cette fameuse case "Se souvenir de moi" lors de la connexion crée justement un cookie qui expose l'utilisateur à ce type d'attaque.
Dans ce cas, vous pouvez mettre en place une re-authentification pour les actions importantes. Par exemple, lors de la suppression d'un compte, redemandez le mot de passe de l'utilisateur. Ainsi, même si quelqu'un a volé le compte, il ne connaît pas le mot de passe et sera bloqué à cette étape.
Certains frameworks gèrent nativement ce niveau d'authentification. Dans Symfony par exemple, vous avez une permission appelée isAuthenticatedFully
. Le système distingue alors deux niveaux :
- Un utilisateur reconnecté avec un cookie "Se souvenir de moi" est considéré comme connecté mais pas complètement authentifié.
- Un utilisateur peut dans ce cas s'authentifier à nouveau avec son mot de passe et le double facteur.
Ensuite, vous pouvez restreindre l'accès à certaines fonctionnalités en fonction du niveau d'authentification.
Sauvegarder des informations clés
Une dernière solution consiste à sauvegarder des informations clés dans les cookies, comme le user agent ou l'IP utilisée pour créer ce cookie. Si cette IP ou le user agent change, on peut considérer que quelqu'un abuse de ce cookie.
Attention cependant, cette solution ne fonctionne pas dans tous les cas. Sur mobile par exemple, l'IP change à chaque changement de connexion, ce qui rendrait le cookie invalide très souvent.
Cette approche peut néanmoins être pertinente pour certains types d'applications. Prenons l'exemple de Twitch : un streamer va généralement toujours streamer du même endroit. On pourrait donc sauvegarder l'IP dans le cookie et l'invalider si elle change, sachant que cet utilisateur ne va pas forcément bouger.
Pour ne pas dégrader l'expérience utilisateur, vous pouvez proposer cette option comme une fonctionnalité supplémentaire dans le compte utilisateur : "Verrouiller l'authentification à cette IP".
Pas de solution parfaite
Malheureusement, il n'existe pas de solution parfaite contre ce type d'attaque. Toutes les solutions ont un impact négatif sur l'expérience utilisateur car elles verrouillent le système de persistance d'authentification.
Ce que vous pouvez également faire, c'est mettre en place des systèmes de suivi pour déboguer le problème. Par exemple, si vous enregistrez les IPs de connexion vous pourrez retracer les anomalies et informer l'utilisateur d'un potentiel vol de jetons.
Dans tous les cas, c'est une attaque qui relève d'une inattention du point de vue utilisateur. Et malheureusement, il n'y aura jamais de solution parfaite contre ce type d'attaque.