Renforcer la sécurité du serveur WebSocket dans sgcWebSockets

· Composants

Un serveur WebSocket exposé sur l'internet public est une cible tentante. Le protocole n'impose aucune limite de taille de message, de sorte qu'une seule connexion peut tenter de faire tomber tout le processus avec une trame conçue à dessein, et le handshake de mise à niveau est un endroit facile pour sonder une validation négligée. La dernière version de sgcWebSockets embarque un ensemble de protections qui ferment ces portes par défaut, afin que votre serveur reste en ligne même sous un trafic hostile.

Tout ce qui suit s'applique aux trois serveurs WebSocket : TsgcWebSocketServer, TsgcWebSocketHTTPServer et le TsgcWebSocketServer_HTTPAPI basé sur http.sys. L'édition .NET hérite des mêmes protections, car elle s'appuie sur la même bibliothèque native.

Une seule limite qui bloque trois attaques mémoire

L'ajout majeur est une unique propriété, MaxMessageSize, qui limite la taille maximale d'un message entrant. Sa valeur par défaut est de 64 MB, ce qui est généreux pour presque toutes les applications, et vous pouvez l'augmenter ou la diminuer, ou la définir à 0 pour désactiver la limite.

Cette seule propriété protège contre trois techniques différentes d'épuisement de la mémoire qui se terminent toutes de la même manière, avec un serveur à court de RAM :

Dans tous les cas, la connexion est fermée proprement avec le close code WebSocket 1009 (Message Too Big), et la mémoire du serveur ne dépasse jamais le plafond.

oServer := TsgcWebSocketServer.Create(nil);
oServer.Port := 80;
// accept messages up to 16 MB, reject anything larger with close 1009
oServer.MaxMessageSize := 16 * 1024 * 1024;
oServer.Active := True;

Analyse sûre de la longueur des trames

Les trames WebSocket peuvent transporter un champ de longueur 64-bit. Selon la RFC 6455, le bit le plus significatif de ce champ doit être à zéro. sgcWebSockets rejette désormais une trame dont la longueur 64-bit a le bit de poids fort activé au lieu de lui faire confiance, de sorte que la limite de taille ci-dessus ne peut pas être contournée par un entier qui déborde. Ce contrôle est toujours actif et ne dépend pas de MaxMessageSize.

Des handshakes plus stricts

Deux nouvelles options sous SecurityOptions renforcent la mise à niveau WebSocket elle-même, et toutes deux sont activées par défaut.

EnforceWebSocketVersion répond à tout handshake qui demande une version autre que 13 par 426 Upgrade Required et un en-tête Sec-WebSocket-Version: 13, au lieu de finaliser la mise à niveau. ValidateWebSocketKey rejette, par 400 Bad Request, tout handshake dont la Sec-WebSocket-Key est absente ou n'est pas un nonce base64 valide de 16 octets. Ces deux contrôles ne s'appliquent qu'au chemin RFC 6455, de sorte que les clients plus anciens utilisant des spécifications héritées ne sont pas affectés.

oServer := TsgcWebSocketServer.Create(nil);
oServer.SecurityOptions.EnforceWebSocketVersion := True;  // 426 on a wrong version
oServer.SecurityOptions.ValidateWebSocketKey := True;     // 400 on a malformed key
// lock the server to your own site while you are at it
oServer.SecurityOptions.OriginsAllowed := 'https://app.example.com';
oServer.Active := True;

Comment cela s'articule avec le pare-feu

Ces protections se situent au niveau de la couche protocole, à l'intérieur de l'analyseur de trames, c'est-à-dire exactement là où surviennent les attaques mémoire. C'est la partie que les composants Firewall et RateLimiter ne peuvent pas atteindre, car ils ne voient un message qu'une fois celui-ci décodé. Les deux couches se complètent : continuez à utiliser le pare-feu et le limiteur de débit pour le filtrage IP, les limites de débit de connexion et de message et la politique d'origine, et laissez les nouvelles limites intégrées protéger l'analyseur lui-même. Pour un serveur public, nous recommandons de définir MaxMessageSize à votre maximum réel, de verrouiller OriginsAllowed sur votre frontal et de plafonner MaxConnections.

Mise à niveau

Les nouvelles protections sont actives dès la mise à jour, avec des valeurs par défaut sûres, de sorte que la plupart des serveurs bénéficient du renforcement de la mémoire et du handshake sans la moindre modification de code. Si votre application échange légitimement des messages de plus de 64 MB, augmentez MaxMessageSize en conséquence. Le code client existant n'est pas affecté.

Mettez à jour depuis la page de téléchargement de sgcWebSockets, ou récupérez-le via GetIt ou votre compte enregistré.

Des questions, des retours ou besoin d'aide pour la migration ? Contactez-nous, vous recevrez une réponse des personnes qui ont écrit le code.