web-dev-qa-db-fra.com

Pourquoi la politique de même origine ne suffit-elle pas à empêcher les attaques CSRF?

Tout d’abord, je suppose un backend qui contrôle les entrées pour éviter les vulnérabilités XSS.

Dans cette réponse @Les Hazlewood explique comment protéger le JWT côté client.

En supposant 100% TLS pour toutes les communications - à la fois pendant et à tout moment après connexion - authentification avec nom d'utilisateur/mot de passe via basic L’authentification et la réception d’un JWT en échange constituent un cas d’utilisation valide . C'est presque exactement comme l'un des flux de OAuth 2 ("mot de passe") travaux. [...]

Vous venez de définir l'en-tête Authorization:

Authorization: Bearer <JWT value here>

Mais cela étant dit, si votre client REST est "non approuvé" (par exemple, un navigateur compatible JavaScript), je ne le ferais même pas: aucune valeur dans le fichier Réponse HTTP accessible via JavaScript - en gros n'importe quel en-tête valeur ou valeur du corps de la réponse - peut être reniflé et intercepté via MITM XSS attaques.

Il est préférable de stocker la valeur JWT dans un cookie sécurisé uniquement, http uniquement (configuration du cookie: setSecure (true), setHttpOnly (true)). Cela garantit que le navigateur va:

  1. ne transmettez jamais le cookie que sur une connexion TLS et,
  2. ne jamais rendre la valeur de cookie disponible pour le code JavaScript.

Cette approche correspond à presque tout ce que vous devez faire pour appliquer les meilleures pratiques Sécurité. La dernière chose à faire est de vous assurer que la protection CSRF est activée sur Chaque requête HTTP afin de garantir que les domaines externes qui initient des requêtes Sur votre site ne peuvent pas fonctionner. _

Le moyen le plus simple de procéder consiste à définir un paramètre sécurisé uniquement (mais PAS uniquement http) cookie avec une valeur aléatoire, par ex. un UUID.

Je ne comprends pas pourquoi nous avons besoin du cookie avec la valeur aléatoire pour nous assurer que les domaines externes générant des requêtes sur votre site ne peuvent pas fonctionner. Cela ne vient pas gratuitement avec la politique de même origine? 

De OWASP

Vérification de l'en-tête d'origine

Le standard d’origine HTTP Header a été introduit en tant que méthode de se défendre contre CSRF et d'autres attaques inter-domaines. Contrairement au référant, l’origine sera présente dans la requête HTTP à l’origine à partir d'une URL HTTPS.

Si l'en-tête Origin est présent, il convient de rechercher cohérence.

Je sais que la recommandation générale de OWASP lui-même est Synchronizer Token Pattern mais je ne vois pas quelles sont les vulnérabilités qui restent dans:

  • TLS + JWT dans un cookie httpOnly sécurisé + stratégie de même origine + aucune vulnérabilité XSS.

UPDATE 1: La règle de même origine s'applique uniquement à XMLHTTPRequest , ainsi un site malveillant peut demander facilement à un formulaire POST de casser sa sécurité. Une vérification explicite de l'en-tête d'origine est nécessaire. L'équation serait:

  • TLS + JWT dans un cookie httpOnly sécurisé + vérification de l'en-tête d'origine _ + aucune vulnérabilité XSS.
27
gabrielgiussi

Résumé

J'avais des concepts mal compris sur la politique de la même origine et la CORS que @Bergi, @ Neil McGuigan et @ SilverlightFox m'ont aidé à clarifier.

Tout d’abord, ce que @Bergi dit à propos de 

SOP n'empêche pas l'envoi de demandes. Cela empêche une page de accéder aux résultats des requêtes interdomaines.

est un concept important. Je pensais qu'un navigateur ne faisait pas la demande au cross-domain conformément à la restriction SOP mais ceci n'est vrai que pour ce que Monsur Hossain appelle une "requête pas si simple" dans ceci excellent tutoriel.

Les demandes d'origine croisée sont de deux types:

  • demandes simples
  • "demandes pas si simples" (un terme que je viens d'inventer)

Les demandes simples sont des demandes qui répondent aux critères suivants:

  • La méthode HTTP correspond à (sensible à la casse) l'une des options suivantes:
    • HEAD
    • GET
    • POST
  • Correspondances d'en-têtes HTTP (insensibles à la casse):
    • Acceptez 
    • Accepter la langue 
    • Contenu-Langue
    • Last-Event-ID
    • Content-Type, mais uniquement si la valeur est l'une des valeurs suivantes:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • texte simple

Ainsi, un POST avec le type de contenu application/x-www-form-urlencoded sera envoyé au serveur (cela signifie une vulnérabilité CSRF) mais le navigateur ne rendra pas les résultats de cette requête accessibles . A POST avec type de contenu application/json est une "demande pas si simple", le navigateur fera donc une demande de préfiguration comme celle-ci.

OPTIONS/terminal HTTP/1.1
Hôte: https://server.com
Connexion: Keep-Alive
Méthode de demande de contrôle d'accès: POST
Origine: https://evilsite.com
En-têtes de demande de contrôle d'accès: type de contenu
Acceptez: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Langue: es-ES, es; q = 0,8

Si le serveur répond avec par exemple:

Access-Control-Allow-Origin: http://trustedsite.com
Méthodes d'accès-contrôle-autorisation: GET, POST, PUT
En-têtes de contrôle d'accès autorisés: content-type
Type de contenu: text/html; jeu de caractères = utf-8

le navigateur ne fera pas la demande du tout, car 

XMLHttpRequest ne peut pas charger http://server.com/endpoint . Réponse à La requête de preflight ne passe pas la vérification du contrôle d'accès: le fichier L'en-tête 'Access-Control-Allow-Origin' contient la valeur non valide "TrustedSite.com". Origin 'evilsite.com' n'est donc pas autorisé.

Donc, je pense que Neil en parlait quand il a souligné que:

la politique de même origine s'applique uniquement à la lecture de données et non l'écrire.

Cependant, avec le contrôle explicite de l'en-tête Origin que j'ai proposé à Bergi, je pense que cela suffit.

En ce qui concerne ma réponse à Neil, je ne voulais pas dire que cette réponse était la réponse à toutes mes questions, mais elle me rappelait un autre problème important concernant SOP et que la règle ne s'appliquait qu'à XMLHTTPRequest.

En conclusion, je pense que l'équation

  • TLS + JWT dans un cookie httpOnly sécurisé + vérification de l'en-tête d'origine + aucune vulnérabilité XSS.

est une bonne alternative si l’API se trouve dans un autre domaine, comme le dit SilverlightFox. Si le client est dans le même domaine que le client, j'aurai des problèmes avec les demandes n'incluant pas l'en-tête Origin. Encore une fois dans le didacticiel cors :

La présence de l'en-tête Origin ne signifie pas nécessairement que le La demande est une demande d'origine croisée. Alors que toutes les demandes d’origine croisée contiendra un en-tête Origin, certaines requêtes de même origine pourraient avoir un aussi. Par exemple, Firefox n'inclut pas d'en-tête Origin sur demandes de même origine. Mais Chrome et Safari incluent un en-tête Origin sur les requêtes POST/PUT/DELETE de même origine (les demandes GET de même origine n'auront pas d'en-tête Origin.).

Silverlight a souligné ceci sur.

Le seul risque qui reste est qu'un client puisse usurper l'en-tête Origin pour qu'il corresponde à l'origine autorisée. La réponse que je cherchais était en fait this

UPDATE: pour ceux qui regardent ce message, j'ai des doutes sur si l'en-tête Origin est nécessaire à l'aide de JWT.

L'équation serait:

  • TLS + JWT stockés dans un cookie sécurisé + JWT dans l'en-tête de la requête + Aucune vulnérabilité XSS.

De plus, l'équation précédente contient le cookie httpOnly, mais cela ne fonctionnera pas si le client et le serveur se trouvent dans des domaines différents (comme de nombreuses applications SPA aujourd'hui), car le cookie ne serait pas envoyé avec chaque demande au serveur. Vous devez donc accéder au jeton JWT stocké dans le cookie et l'envoyer dans un en-tête.

11
gabrielgiussi

Pourquoi la politique de même origine ne suffit-elle pas à empêcher les attaques CSRF?

Parce que la politique de même origine s'applique uniquement à la lecture des données et non à leur écriture. 

Vous voulez éviter à http://compromised.com de faire une requête comme celle-ci (depuis le navigateur de l'utilisateur):

POST https://example.com/transfer-funds
fromAccountId:1
toAccountId:666

Une demande légitime ressemblerait à ceci:

POST https://example.com/transfer-funds
fromAccountId: 1
toAccountId: 666
csrfToken: 249f3c20-649b-44de-9866-4ed72170d985

Pour ce faire, vous demandez une valeur (le jeton CSRF) qui ne peut pas être lue par un site externe, c'est-à-dire dans une valeur de formulaire HTML ou un en-tête de réponse.

En ce qui concerne l’en-tête Origin, les anciens navigateurs ne le prennent pas en charge et Flash présentait certaines vulnérabilités qui permettaient au client de le modifier. En gros, vous feriez confiance à Adobe pour ne rien foirer dans le futur ... Cela vous semble-t-il une bonne idée? 

assurez-vous que vous avez la protection CSRF sur chaque requête HTTP

Vous avez uniquement besoin de la protection CSRF pour les demandes ayant des effets secondaires, telles que le changement d'état ou l'envoi d'un message.

11
Neil McGuigan

Je veux juste résumer les réponses.

  1. Comme mentionné ailleurs, SOP s'applique uniquement à XmlHttpRequests. Cela signifie que, par spécification, les navigateurs doivent envoyer l’en-tête Origin avec les demandes qui ont été effectuées au moyen de XmlHttpRequests. 
  2. Si vous cochez Chromium, vous envoyez également Origin lorsque vous soumettez le formulaire. Cependant, cela ne signifie pas que les autres navigateurs le font. L'image ci-dessous illustre deux requêtes de publication effectuées dans Firefox. L'une est réalisée en soumettant un formulaire et une seconde en utilisant XHR . Les deux demandes ont été faites du http://hack:3002/changePassword au http://bank:3001/chanePassword
  3. Le navigateur est autorisé à ne pas envoyer l'en-tête Origin si une demande a été effectuée à partir du même domaine. Le serveur doit donc vérifier la stratégie d'origine uniquement lorsque l'en-tête Origin est défini.

La conclusion est la suivante: si vous utilisez des cookies et qu'une requête parvient au serveur sans en-tête Origin, vous ne pouvez pas savoir si cela a été fait en soumettant un formulaire provenant d'un autre domaine ou de XHR dans le même domaine. C'est pourquoi vous avez besoin d'une vérification supplémentaire avec CSRF.

 enter image description here

0
deathangel908