Ils sont là, bien cachés, prêts à nous bondir sur le coin du nez avec leurs grosses erreurs rouges venant défigurer la console de notre navigateur.
Je parle des entêtes CORS, ces fameux entêtes qui viennent vous rappeler que non, tout ne roule pas systématiquement sur des roulettes.
Et si je vous disais que les CORS étaient là en réalité pour vous protéger ?
Les cookies laissent des miettes
Avant de rentrer dans quoi que ce soit comme explication, il est fondamental de revenir sur ce qui est un des plus gros risques dans un navigateur : les cookies.
Alors non, dans les faits, les cookies ne représentent pas le moindre danger, cependant il faut savoir que chaque requête HTTP contient systématiquement les cookies liés au domaine appelé.
Cela signifie que si je fais une requête sur https://mabanque.fr/solde, tous les cookies liés à ce domaine présents sur mon navigateur seront transmis dans la requête.
C’est de cette manière que les cookies transitent, lorsqu’ils ont été déposés sur le navigateur, ils sont automatiquement intégrés aux requêtes sortantes.
C’est d’ailleurs pour cette raison que vous pouvez voir les domaines associés aux cookies dans votre console.
Lorsque nous nous authentifions sur un site, généralement le site va déposer un cookie contenant un identifiant de session, voir un token. De cette manière, lorsque nous effectuons des requêtes vers le site en question, il peut récupérer l’identifiant de la session contenue dans les cookies pour s’assurer que l’utilisateur est bien connecté et ainsi lui donner accès à la ressource demandée.
C’est donc à l’aide des cookies que nous pouvons rester connectés à un site internet.
Requêtes Cross Domain et récupération d’informations sensibles
Imaginons un scénario basique dans un monde où la sécurité ne serait pas prise en compte.
Nous nous rendons sur un site quelconque sans savoir que celui-ci a décidé de nous dépouiller. Lorsque nous arrivons sur le site, il charge du Javascript qui va faire des requêtes vers notre banque. Cette requête va tenter de récupérer le solde du compte par exemple, voir des informations nettement plus sensibles.
Il est à noter que je me suis connecté récemment à ma banque en ligne, j’ai alors encore des cookies qui contiennent les informations de ma session.
Le site de l’attaquant faisant une requête vers ma banque, celle-ci contient tous les cookies nécessaires pour que ma banque réponde favorablement à la requête.
De cette manière, l’attaquant peut faire tous les appels API qu’il souhaite en exploitant la présence de cookies sur notre navigateur.
Comment empêcher les requêtes Cross Domain ?
Il est important ici de prendre en compte une restriction non négligeable : de base, les navigateurs refusent les requêtes vers un autre domaine que celui sur lequel vous êtes.
Concrètement, je suis sur le site https://uneembrouile.com qui tente de faire une requête AJAX vers https://mabanque.fr, à moins que l’API mabanque.fr ait explicitement autorisé le domaine uneembrouille.com à faire des requêtes, le navigateur va gentiment mettre un stop à la requête en affichant une magnifique erreur :
Avec ce mode de fonctionnement, les appels vers des API tierces sont bloqués par défaut et le site qui voulait initialement me dépouiller n’a plus qu’une chose à faire : rester en chien.
Mais pour le coup, comment permettre à une application de faire des requêtes sur un autre domaine ?
C’est ici que CORS intervient en permettant de déclarer explicitement quel site peut consommer les ressources d’un serveur.
Comment fonctionne CORS ?
Au fait, nous avons parlé de la signification de CORS ?
Cross-Origin Resource Sharing
C‘est un mécanisme qui se base sur des entêtes (ou headers) contenu dans les réponses des API indiquant si le domaine appelant peut accéder, ou non, à la ressource demandée.
Globalement le mode de fonctionnement est assez basique. Comme nous l’avons vu précédemment, de base, le navigateur bloque toutes les requêtes vers un autre domaine que celui de la page en cours de consultation. Pour pouvoir appeler un domaine tiers, il faut nécessairement qu’il nous y autorise explicitement.
Pour autoriser, c’est assez simple, le serveur sur l’autre domaine doit répondre avec au minimum une entête Access-Control-Allow-Origin
contenant soit le domaine appelant, soit un wildcard (*).
Imaginons maintenant un nouveau scénario.
Je me rends sur le site https://pasdembrouille.fr/ et celui-ci souhaite faire des requêtes vers https://unsitesensible.fr/.
Normalement, les requêtes devraient être bloquées par le navigateur, cependant, les deux sites travaillent ensemble et https://unsitesensible.fr/ répond aux requêtes de pasdembrouille.fr avec ce header en particulier :
Access-Control-Allow-Origin: pasdembrouille.fr
Avec ce header, le navigateur comprend que la requête est légitime. Il la laisse passer.
Ici il est à noter que ce mode de fonctionnement permet de déterminer explicitement quels sont les sites (domaines) pouvant utiliser l’API. Utiliser un wildcard (*
) c’est rendre Open Bar son API. Dans certains cas c’est souhaité, mais il est nécessaire de bien comprendre que l’utilisation d’un wildcard fait sauter ce qui est à l’origine une sécurité.
Requête de Preflight
Requêtes concernées par CORS
Ce ne sont pas toutes les requêtes qui sont concernées. À vrai dire, ce ne sont que les requêtes initiées par AJAX.
Les autres requêtes comme le chargement d’images, de feuilles de style ou même de scripts, peuvent se faire Cross Domain sans problème.
À vrai dire elles ne posent pas trop de problèmes. Il y a bien les attaques CSRF mais c’est un autre sujet, que peut-être nous traiterons dans un prochain article.
Comment contourner CORS ?
Soyons parfaitement clairs, il est possible de contourner les restrictions mais pas de récupérer les cookies pour le domaine de l’API cible.
Les deux solutions présentées juste après sont totalement différentes.
La première, JSONP, doit être mise en place par le fournisseur de l’API. Généralement cette solution est proposée pour des ressources accessible en lecture seule.
Quant à la seconde, elle est mise en place par celui qui souhaite consommer l’API sans avoir la possibilité de modifier l’API elle-même.
JSONP
JSONP ou JSON with Padding, est une solution permettant d’appeler une API en exploitant l’absence de restriction sur le chargement de script JS.
Dans les faits, il est nécessaire de déclarer une fonction qui recevra la réponse de l’API dans le scope global
Utilisation d’un proxy intermédiaire
Vous avez besoin de faire des appels à une API publique ne proposant pas de headers vous autorisant à effectuer des requêtes ?
Une solution est l’utilisation d’un Proxy entre la page web et l’API.
Un Proxy n’est rien d’autre qu’un serveur web qui transmet les requêtes qui lui sont faites a un autre serveur (un API plus précisément) et retour la réponse du serveur au client.
[schema]
Comme les restrictions CORS n'ont lieux que dans un navigateur, si c’est un server qui appelle l’API, le problème ne se pose plus.