Table des matières
Avant propos
Initialement prévu pour le partage documentaire, le web est devenu ces vingts dernières années un protocole de communication multi-usage. Que ce soit des sites informatifs purement documentaires (documentation, présentations commerciales, …), des boutiques en ligne ou des applications scientifiques au niveau, le web est devenu l’acteur principal de l’internet.
Néanmoins, le protocole http est conçu autour de plusieurs principes qui ont fait son succès :
- communication state-less 1 : Cette conception lui offre résilience et performance,
- une interface standardisée : qui permet à plusieurs clients web (navigateurs web) de pouvoir cohabiter,
- fonctionnement décentralisé : qui permet à n’importe qui de pouvoir créer une application ou un site sans autorisation préalable
Or, afin de concevoir des applications complexes, il a vite été nécessaire de pouvoir gérer des flux complexes. Les sites marchands, par exemple, ont besoin de conserver le panier d’achat d’un chargement à l’autre.
Pour répondre à ces besoins, le web repose sur deux principes :
- les cookies : qui sont des informations conservées coté client et qui permettent de conserver un historique de navigation,
- les sessions : qui sont des informations conservées coté serveur
Mais toutes ces interactions reposent sur deux composants qui n’ont aucune raison de considérer l’autre comme fiable :
- le navigateur web : qui doit se méfier des sites web qu’ils consultent, car certains ont des utilisant malveillante des données qui peuvent leur être transmise
- les serveurs web : qui doit se méfier des clients web qui les consultent, car certains ont une utilisation malveillante des données disponibles
1. Quelles menaces pour la sécurité des systèmes d’information (CSRF) ?
Avant d’expliquer le fonctionnement des technologies mises au point, il est nécessaire de faire un point sur le type de menace que ces technologies limitent.
Dans le cas classique d’une application web, un serveur web (https://www.labo.in2p3.fr) s’occupe de deux fonctions différentes :
- le frontend qui fourni aux utilisateurs l’interface web (du html pour résumé),
- le backend qui fourni l’interface entre la base de donnée et le frontend.
Dans des configurations plus complexes, ces deux fonctions sont séparé et les deux serveurs communiquent via des API. La plus commune actuellement est l’API REST.
L’exemple suivant est volontairement simplifié, même si le principe de l’attaque est bien celui présenté, les moyens de préparation et d’exécution de l’attaque peut-être plus complexe. De plus, même si l’attaque fait appelle à une composante de chance (l’utilisateur doit être connecté), il faut relativiser celle-ci au vu de l’assiette potentiel de l’attaque (une campagne de phishing massif par exemple).
Imaginons que vous développiez un site bancaire, ce qui de site nécessite une infrastructure complexe et vous décidez de séparer le frontend et le backend. Chaque utilisateur se connecte sur votre frontend qui intègre un code javascript qui redirige sur le backend2. Le backend, génère une session qui va permettre à l’utilisateur de consulter ses comptes bancaire, faire des virements, …
Maintenant, supposons que pour faire un virement bancaire l’API du backend propose une interface du type
https://api.mabanque.fr/virements?montant=<valeur>&destination=<IBAN>
. Biensûr cette API n’est disponible que si une
session est active entre le navigateur et votre site bancaire. Seul l’utilisateur depuis son navigateur peut effectuer
cette requête.
Maintenant, supposons que l’utilisateur aille sur un site http://www.super-site.com, ce site embarque un code javascript malicieux qui provoque une requête vers votre site bancaire. La requête provenant de votre navigateur web est accepté par votre site et le virement est effectué de manière transparente.
Ce type d’attaque se nomme CSRF pour Cross Site Request Forgery, le principe est de provoquer des requêtes vers d’autres sites qui n’ont pas suffisamment sécurisé leurs infrastructures.
Ce type d’attaque repose sur plusieurs failles :
- le cookie de session est envoyé par le navigateur vers le site bancaire ce qui permet au site bancaire de reconnaître comme valide la requête (cf. chapitre sur les cookies)
- le navigateur accepte qu’un code javascript permette de créer une requête sur un site qui n’est pas le site d’origine de la requête (cf. chapitre sur CORS)
- le format de la requête est prédictible et aucun mécanisme comme un token aléatoire permet de forcer une pré-validation de la requêtre (cf. chapitre sur CSTFToken)
2. Les cookies
Les cookies sont des informations de navigation qui sont stockés dans votre navigateur web afin de conserver un historique de communication.
Il existe cependant deux problèmes de sécurité liés à l’utilisation des cookies :
- traçage : en effet, si je définis un cookie vous permettant de vous identifier et que mon site a vocation à être utilisé par plusieurs autres sites (google analytics, …) alors je suis capable de tracer l’activité des personnes. Il n’y a pas de réponse technique à ce problème, néanmoins le cadre de la RGPD3 offre un cadre législatif protecteur,
- utilisation abusive : la conservation et l’utilisation des cookies est lié au navigateur web, or, il est commun d’utiliser le même navigateur web pour surfer sur internet et pour aller sur vos sites marchands. Comment s’assurer que le site http://www.super-video.com n’utilise pas les cookies de https://www.mabanque.com ?
Aujourd’hui, la sécurisation des cookies est entièrement déléguée au navigateur web. Les acteurs du web ont normalisé la communication entre les serveurs et les navigateurs afin de savoir dans quel cadre utiliser un cookie. On distingue deux types de cookies :
- cookie propre : ceux générés par le site que l’on consulte. Ils sont accessibles à ce site et son transmis à chaque communication entre le client web et le serveur. De plus, le client web peut les consulter directement via javascript
- cookie tier : ceux générés par d’autre site que celui que l’on consulte. Le plus célèbre est google analytics mais d’autres raisons peuvent expliquer un cookie tier comme le développement d’une infrastructure distribuée ou le frontend est sur un serveur différent que le backend. Ces cookies suivent une politique de transmission liée à la configuration du serveur web (voir chapitre ci-dessous). Les informations ne sont pas directement consultable par le client web. Par exemple, il n’est pas possible de consulter via javascript le contenu d’un cookie tier, même si sa transmission est autorisé par le serveur.
Pour gérer la publication des cookies tiers, le site qui génère le cookie associe trois paramètres à ce cookie :
- HTTPOnly : ce paramètre permet de dire si le cookie ne doit être publié dans le cadre d’une navigation web classique (true) ou s’il est autorisé de publier ce cookie dans le cadre d’une transaction ajax (javascript).
- SameSite : ce paramètre défini si le cookie doit être publié :
- Strict: que si le site qui effectue la requête est le site qui a créé le cookie
- Lax: que si le site est le créateur du cookie ou s’il s’agit d’un lien hypertext
- None: le cookie sera toujours publié
- Secure : permet de définir si le cookie n’est envoyé que lorsqu’il s’agit d’un protocole sécurisé (https) ou non.
Aujourd’hui, les navigateurs web considèrent par défaut qu’un cookie est Lax. Cela veut dire qu’un navigateur web moderne, sauf contre ordre du serveur qui a généré le cookie, ne transmettra pas le cookie au serveur dans un autre cadre qu’un lien hypertext.
De plus, les navigateurs modernes vont bientôt considérer que les cookies SameSite = None devront être associé au paramètre Secure = True.
La sécurisation des cookies telle que vu permet de limiter les attaques dans les cas ou le service est assuré par un serveur unique et où peu de transaction entre différents serveurs est nécessaire. Le fait de considérer les cookies comme Lax par défaut assure une protection efficace pour les applications développées sans compétences particulières.
3. Cross-Origin Resource Sharing (CORS)
La sécurisation des cookies permet de limiter l’assiette des menaces numériques, seulement lorsque nous devons développer des applications complexes avec des interactions entre plusieurs serveurs différents où les cookies deviennent HTTPOnly=false, SameSite=None, Secure=True pour pouvoir satisfaire le workflow, d’autres moyens doivent être mis en place.
Le CORS est un standard permettant au serveur de définir quel site peut être à l’origine d’une requête sur un backend. Reprenons notre exemple précédent, supposons que notre infrastructure à un serveur frontend qui redirige vers un serveur backend. Notre cookie de session est SameSite=None, Secure=True* car le site initiateur de la requête est **frontend et non backend.
Le CORS va permettre:
- au backend de définir que frontend est légitime à rediriger des requêtes, lorsque le navigateur va être
redirigé sur le backend, il va demander à celui-ci qui est autorisé à initier des requêtes via le header
Access-Control-Allow-Origin
par exempleAccess-Control-Allow-Origin: https://frontend
. - le navigateur prend en compte le header et refuse toute connexion sur backend initiée par une autre source que https://frontend. Par exemple, le site https://www.super-site.com ne sera pas autorisé à faire une requête.
Par défaut, les navigateurs considèrent que les sites qui ne fournissent pas de Access-Control-Allow-Origin
n’accepte aucune requête de cross-origin. Encore une fois, cela permet d’avoir un fonctionnement sécurisé par défaut
qui demande à être volontairement modifié pour être désactivé.
Le cross-origin à néanmoins quelques limites :
- il ne gère pas les sous-domaines, si labo.in2p3.fr est accepté alors vilain.labo.in2p3.fr l’est aussi
- il repose sur le fait que le navigateur prend en charge CORS, et donc est une sécurité coté client et non coté serveur
4. Cross-Site Request Forgery Token
Le dernier mécanisme de protection dans le cas d’attaque CSRF se trouve coté serveur. Dans le chapitre deux, nous expliquions que l’attaque était possible car la requête était prévisible et qu’il était simple de créer une requête valide.
Afin de palier cette faiblesse, les serveurs proposent un mécanisme de csrftoken. Le principe est de fournir, lors de la requête web précédente, à l’utilisateur un token aléatoire qu’il va ajouter à la requête pour que celle-ci soit accepter. Par exemple :
- le serveur va fournir un cookie csrftoken, ce cookie étant tier, sa valeur ne peut pas être lu directement par le javascript dans le navigateur web
- le client doit ajouter ce csrftoken dans la requête, par exemple
https://api.mabanque.com/?montant=<valuer>&destination=<IBAN>&csrftoken=<token>
. Ainsi un site malveillant n’aura aucun moyen de générer une requête valide, - le token utilisé devient invalide et un nouveau token est généré
Cette mesure permet au serveur de s’assurer que les requêtes sont bien sécurisé, néanmoins elle est particulièrement aggressive. Son implémentation est dépendante du framework de développement applicatif utilisé (Django, Symfony, …).
Conclusions
L’ensemble de ces mesures ont été développer par les acteurs du web (développeurs de navigateur, développeurs de serveur web, gestionnaires de services) afin de fournir un internet sécurisé et ouvert. Chacune des technologies mises en place a pour objectif de travailler en symbiose avec les autres technologies.
Par défaut, les applications simples ne devraient pas avoir besoin de compétences particulières pour fonctionner, mais avant de désactiver ou modifier la configuration d’un mécanisme, il est nécessaire de se demander quels impacts cette modification peut avoir sur votre infrastructure.
-
Une communication state-less est une communication qui ne conserve pas d’historique. Il n’y a donc aucune gestion de flux de travail permettant une validation. ↩
-
Ce type d’architecture est commune et fait parti des bonnes pratiques web. Il n’est pas question ici de remettre en cause l’architecture. ↩
-
Règlement général de la protection des données : il s’agit d’une loi Européenne obligeant le respect d’un certain nombre de contraintes quant à l’utilisation des données personnelles ou identifiantes ↩