C.O.R.S.

DĂ©finitions

Cross-Origin Resource Sharing. https://www.w3.org/TR/cors/​

L’ "origin" (https://tools.ietf.org/html/rfc6454) est composĂ© des Ă©lĂ©ments suivants :

  • Scheme : http / https / 


  • FQDN : www.attacker.com / api.target.com / 


  • Port : 80 / 443 / 8000

Fonctionnement

C.O.R.S. Flowchart

Supposons que nous avons deux “origins” : https://attacker.com et https://target.com.

GET ou FETCH

Par dĂ©faut, si l’application https://attacker.com Ă©met une requĂȘte GET depuis le browser (en JavaScript) vers l’origin https://target.com, celle-ci ne transmettra aucun des cookies des deux origins.

Le browser analysera ensuite certains headers C.O.R.S. (que nous verrons plus tard) mais en leur absence, il ne transmettra pas la rĂ©ponse Ă  l’application. Error: No 'Access-Control-Allow-Origin' header is present on the requested resource

Autre

S’il s’agit d’une requĂȘte autre que GET (ou similaire HEAD
) le browser envoie une preflight request de type OPTIONS pour vĂ©rifier si la requĂȘte est autorisĂ©e en fonction de l’ origin et de la mĂ©thode utilisĂ©e.

MĂ©fiez-vous des Fausses Solutions

Ces mécanismes ont été mis en place pour éviter les attaques de type C.S.R.F (Cross Site Request Forgery).

Malheureusement, le premier rĂ©sultat sur lequel on tombe en recherchant le message d’erreur est le suivant : https://stackoverflow.com/questions/20035101/why-does-my-javascript-get-a-no-access-control-allow-origin-header-is-present​

On y trouve les propositions suivantes :

Sauvés par le C.O.R.S.

AprĂšs la mise en place du header Access-Control-Allow-Origin: *, la requĂȘte Ă©mise depuis l’origin https://attacker.com vers https://target.com ne contient pas de cookies.

Il faut activer l’option withCredentials de l’objet XHR ou de la fonction fetch avec le paramùtre credentials: 'include'.

La requĂȘte est alors envoyĂ©e avec les cookies mais encore une fois les spĂ©cifications C.O.R.S. sont rigoureuses et il n’est pas possible de rĂ©cupĂ©rer le contenu de la rĂ©ponse si le header Access-Control-Allow-Origin vaut *.

Pour pouvoir transmettre des cookies et rĂ©cupĂ©rer la rĂ©ponse, il faut configurer le header Access-Control-Allow-Credentials mais encore une fois, heureusement que ce n’est pas suffisant. Cette fonctionnalitĂ© ne peut pas ĂȘtre activĂ©e si Access-Control-Allow-Origin vaut *.

Il faut donc dĂ©finir une whitelist d’origins mais malgrĂ© tous ces obstacles volontaires, certains vont jusqu’au bout
 http://stackoverflow.com/questions/26411480/angularjs-a-wildcard-cannot-be-used-in-the-access-control-allow-origin-he​

Please don’t!!!

AprĂšs cette ultime Ă©tape, n’importe quelle application depuis n’importe quel origin peut communiquer librement avec votre API en utilisant les credentials prĂ©sents dans les cookies de l’utilisateur actuellement authentifiĂ©.

I Will Never Use Cookies Again

Par prĂ©caution, mĂȘme en l’absence de cookies, il vaut mieux Ă©viter d’utiliser la valeur * pour le header Access-Control-Allow-Origin sauf dans le cas d'une API publique.

Il est prĂ©fĂ©rable d’implĂ©menter une logique de whitelist sur l’API qui vĂ©rifie le contenu du header Origin de la requĂȘte et le renvoie dans le header Access-Control-Allow-Origin de la rĂ©ponse en cas d’autorisation rĂ©ussie.

La vĂ©rification de la whitelist doit ĂȘtre stricte ! Il ne suffit pas de vĂ©rifier le FQDN.

Pensez à implémenter une rÚgle sur votre W.A.F. (Web Application Firewall), middlewares ou monitoring sécurité pour détecter et bloquer les réponses HTTP contenant le header Access-Control-Allow-Credentials.

Attention ! Les certificats clients et l’authentification de type "basic auth" sont Ă©galement considĂ©rĂ©s comme des credentials et on rencontre les mĂȘmes problĂšmes qu’avec les cookies.