A quoi sert Sec-WebSocket-Key?
Dans la section 1.3 "ouverture de la poignée de main" de draft-IETF-hybi-thewebsocketprotocol-17 , il décrit Sec-WebSocket-Key
comme suit:
Pour prouver que la poignée de main a été reçue, le serveur doit prendre deux informations et les combiner pour former une réponse. La première information provient du champ |Sec-WebSocket-Key| header dans la poignée de main du client:
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Pour ce champ d'en-tête, le serveur doit prendre la valeur (telle que présente dans le champ d'en-tête, par exemple la version [RFC4648] codée en base64 moins les espaces de début et de fin), et concaténez-le avec L'identifiant global Unique (GUID, [RFC4122]) "258EAFA5-E914-47DA-95CA - C5AB0DC85B11" sous forme de chaîne, qui est peu susceptible d'être utilisé par les points de terminaison du réseau qui ne comprennent Un hachage SHA - 1 (160 bits), codé en base64 (voir Section 4 de [RFC4648]), de cette concaténation est ensuite renvoyé dans la poignée de main du serveur [FIPS.180-2.2002].
Voilà le truc Je ne comprends pas: pourquoi ne pas simplement renvoyer le code 101? Si l'utilisation correcte de Sec-WebSocket-Key
est pour la sécurité, ou pour prouver qu'ils peuvent gérer les requêtes websocket, alors n'importe quel serveur pourrait renvoyer la clé attendue s'il le voulait, et prétendre qu'il est un serveur WebSocket.
3 réponses
Selon la norme RFC 6455 Websocket
.. the server has to prove to the client that it received the
client's WebSocket handshake, so that the server doesn't accept
connections that are not WebSocket connections. This prevents an
attacker from tricking a WebSocket server by sending it carefully
crafted packets using XMLHttpRequest [XMLHttpRequest] or a form
submission.
...
For this header field, the server has to take the value (as present
in the header field, e.g., the base64-encoded [RFC4648] version minus
any leading and trailing whitespace) and concatenate this with the
Globally Unique Identifier (GUID, [RFC4122]) "258EAFA5-E914-47DA-
95CA-C5AB0DC85B11" in string form, which is unlikely to be used by
network endpoints that do not understand the WebSocket Protocol.
The |Sec-WebSocket-Key| header field is used in the WebSocket opening
handshake. It is sent from the client to the server to provide part
of the information used by the server to prove that it received a
valid WebSocket opening handshake. This helps ensure that the server
does not accept connections from non-WebSocket clients (e.g., HTTP
clients) that are being abused to send data to unsuspecting WebSocket
servers.
Donc, comme la valeur du GUID est spécifiée dans la norme, il est peu probable (possible, mis avec une très faible probabilité) que le serveur qui n'est pas au courant des Websockets l'utilise. Il ne fournit aucune sécurité (secure websockets - WSS:// - does), il garantit simplement que le serveur comprend le protocole websockets.
Vraiment, comme vous avez mentionné, si vous êtes au courant des websockets (c'est ce qu'il faut vérifier), vous pouvez prétendre être un serveur websocket en envoyant une réponse correcte. Mais alors, si vous n'agissez pas correctement (par exemple, formez correctement les cadres), cela sera considéré comme une violation du protocole. En fait, vous pouvez écrire un serveur websocket incorrect, mais il n'y aura pas beaucoup d'utilisation.
Et un autre but est d'empêcher les clients de demander accidentellement la mise à niveau de websockets de ne pas l'attendre (disons, en ajoutant manuellement les en-têtes correspondants, puis en attendant smth else). Il est interdit de définir Sec-WebSocket-Key et d'autres en-têtes connexes à l'aide de la méthode setRequestHeader
dans les navigateurs.
Surtout pour le casse-cache.
Imaginez un serveur proxy inversé transparent regardant le trafic HTTP passer. S'il ne comprend pas WS, il pourrait mettre en cache par erreur une poignée de main WS et répondre avec un 101 inutile au client suivant.
En utilisant un nonce (la clé) et en exigeant une réponse de défi de base plutôt spécifique à WS, le serveur a compris qu'il s'agissait d'une poignée de main WS et indique au client que le serveur écoutera sur le port. Cache reverse-proxy n'implémenterait jamais cette logique de hachage "par erreur".
Je suis enclin à être d'accord.
Rien d'important ne changerait si le client ignorait la valeur de L'en-tête Sec-WebSocket-Accept.
Pourquoi? Parce que le serveur ne prouve rien en faisant ce calcul (à part qu'il a le code pour faire le calcul). À peu près la seule chose qu'il exclut est un serveur qui répond simplement avec une réponse en conserve.
L'échange d'en-têtes (par exemple avec des valeurs 'key' et 'accept' fixes) est déjà suffisant pour exclure toute connexion accidentelle avec quelque chose qui n'essaie pas au moins D'être un serveur WebSocket; et s'il essaie, l'exigence qu'il fasse ce calcul n'est guère un obstacle à sa réussite.
Les revendications RFC:
".. le serveur doit prouver au client qu'il a reçu le la liaison WebSocket du client, de sorte que le serveur n'accepte pas connexions qui ne sont pas des connexions WebSocket."
Et:
" cela aide assurez-vous que le serveur n'accepte pas les connexions provenant de clients non-WebSocket .."
AUCUNE de ces revendications n'a de sens. Le serveur n'est jamais celui qui rejette la connexion car c'est celui qui calcule le hachage, pas celui qui le vérifie.
Ce genre d'échange aurait du sens si le GUID magique n'était pas corrigé, mais était plutôt un secret partagé entre le client et le serveur. Dans ce cas l'échange permettrait au serveur de prouver au client qu'il avait le secret partagé sans le révéler.