web-dev-qa-db-fra.com

Pourquoi n'y a-t-il pas de politique de même origine pour WebSockets? Pourquoi puis-je me connecter à ws: // localhost?

J'aimerais utiliser WebSockets pour la communication inter-processus de mon application (Daemon <-> WebGUI et Daemon <-> FatClient, etc.). Pendant les tests, j'ai essayé de me connecter à mon serveur de socket Web exécuté localement (ws: // localhost: 1234) via le client JavaScript WebSocket sur websocket.org ( http://www.websocket.org/echo.html ).

Ma question maintenant est:
Pourquoi est-ce possible? N'y a-t-il pas de politique de cross-Origin implémentée dans les navigateurs (ici: FF29 sous Linux)?

Je demande parce que si websocket.org était diabolique, il pourrait essayer de communiquer avec mon serveur WS local et rediriger chaque message reçu de localhost vers un autre serveur:

 Navigateur de serveur WebSocket local Serveur Web malveillant 
 À l'adresse ws: // localhost: 1234 à http: //evil.tld 
 | | | 
 | | ------ [GET /]--------->|
 | | <----- [HTML + EvilJS] ---- | 
 | <------ [se connecter ws: // ..] ---- | | 
 | <---- [certaines communications] -> | | 
 | | ---- [mal en avant] ----> | 
 | | | 

Je n'ai pas testé l'ensemble du cas d'utilisation, mais la connexion à ws: // localhost du serveur JS fourni par websocket.org fonctionne définitivement.

73
binwiederhier

oberstet a répondu à la question . Merci! Malheureusement, je ne peux pas le marquer comme "correct" car c'était un commentaire. Le navigateur envoie l'en-tête "Origin" qui peut être vérifié par l'application.

Dans Java [1]:

@Override 
 Public void onOpen (WebSocket clientSocket, poignée de main ClientHandshake) {
 Chaîne clientOrigin = handshake.getFieldValue ("Origine"); 
 
 If (clientOrigin == null ||! clientOrigin.equals (WEBSOCKET_ALLOWED_Origin_HEADER)) {
 logger.log (Level.WARNING, "Le client n'a pas envoyé l'en-tête d'origine correct:" + clientOrigin); 
 
 clientSocket.close (); 
 return; 
} 
 
 // ... 
}

[1] using https://github.com/TooTallNate/Java-WebSocket

39
binwiederhier

Pour aborder le "Pourquoi?" En partie, la raison pour laquelle les navigateurs n'appliquent pas la règle de même origine (dont CORS est un assouplissement) pour WebSockets, contrairement aux appels AJAX, parce que les WebSockets ont été introduits après la valeur des demandes croisées. établies, et parce qu'elles ne sont pas soumises à SOP, les raisons historiques des vérifications effectuées par le client CORS ne s'appliquent pas.

Pour AJAX, à l'époque d'une politique globale à origine unique, les serveurs ne s'attendaient jamais à ce qu'un navigateur authentifié envoie une demande provenant d'un domaine différent.1, et donc pas besoin de s'assurer que la demande venait d'un endroit de confiance2. Les relaxations ultérieures telles que CORS devaient faire l’objet de vérifications côté client afin d’éviter d’exploiter les applications existantes en abusant en violant cette hypothèse (en effectuant effectivement une opération attaque CSRF ).

Si le Web était inventé aujourd'hui, sachant ce que nous savons maintenant, ni SOP ni CORS ne seraient nécessaires pour AJAX et il est possible que toute la validation soit laissée au serveur.

Les WebSockets, étant une technologie plus récente, sont conçues pour prendre en charge dès le départ les scénarios inter-domaines. Toute personne qui écrit dans la logique du serveur doit être consciente de la possibilité de requêtes cross-Origin et procéder à la validation nécessaire, sans qu'il soit nécessaire de prendre des précautions lourdes du côté du navigateur, à la manière de CORS.


1 Ceci est une simplification. Les requêtes GET Cross-Origin pour des ressources (y compris les balises <img>, <link> et <script>) et pour la soumission de formulaires POST ont toujours été autorisées en tant que fonctionnalité fondamentale du Web. De nos jours, les appels AJAX _ dont les requêtes ont les mêmes propriétés sont également autorisés. Ils sont également appelés de simples requêtes multi-origines . Toutefois, l'accès aux données renvoyées à partir de telles demandes dans le code n'est pas autorisé, sauf autorisation explicite des en-têtes CORS du serveur. De plus, ce sont ces "simples" POST requêtes qui sont la raison principale pour laquelle les jetons anti-CSRF sont nécessaires pour que les serveurs se protègent des sites Web malveillants.

2 En fait, un moyen sécurisé de vérifier la source de la demande n'était même pas disponible car l'en-tête Referer peut être falsifié, par exemple. en utilisant une vulnérabilité de redirection ouverte. Cela montre également à quel point les vulnérabilités CSRF étaient mal comprises à l'époque.

36
staafl

Les WebSockets peuvent communiquer entre domaines et ne sont pas limités par le SOP (politique de même origine)).

Le même problème de sécurité que vous avez décrit peut survenir sans WebSockets.

Le mauvais JS peut:

  • Créez une balise script/image avec une URL vers evil.tld et placez les données dans la chaîne de requête.
  • Créez une balise de formulaire, placez les données dans les champs et appelez l'action "submit" du formulaire, en effectuant une requête HTTP POST, qui peut être interdomaine. AJAX est limité par la SOP, mais un HTTP normal POST ne l’est pas. Vérifiez le problème de sécurité Web XSRF.

Si quelque chose injecte du javascript dans votre page ou si vous obtenez du javascript malveillant, votre sécurité est déjà cassée.

16
vtortola