Rafforzare la sicurezza del server WebSocket in sgcWebSockets

· Componenti

Un server WebSocket esposto su internet pubblico è un bersaglio allettante. Il protocollo non prevede alcun limite integrato sulla dimensione dei messaggi, quindi una singola connessione può tentare di mettere in ginocchio l’intero processo con un solo frame creato ad arte, e l’handshake di upgrade è un punto facile dove sondare validazioni approssimative. L’ultima versione di sgcWebSockets include una serie di protezioni che chiudono queste porte per impostazione predefinita, così il tuo server resta attivo anche sotto traffico ostile.

Tutto quanto segue si applica a tutti e tre i server WebSocket: TsgcWebSocketServer, TsgcWebSocketHTTPServer e TsgcWebSocketServer_HTTPAPI basato su http.sys. L’edizione .NET eredita le stesse protezioni, perché gira sulla stessa libreria nativa.

Un solo limite che ferma tre attacchi alla memoria

L’aggiunta principale è un’unica proprietà, MaxMessageSize, che limita la dimensione massima di un messaggio in entrata. Il valore predefinito è 64 MB, generoso per quasi ogni applicazione, e puoi aumentarlo o ridurlo, oppure impostarlo a 0 per disabilitare il limite.

Quella singola proprietà difende da tre diverse tecniche di esaurimento della memoria che finiscono tutte allo stesso modo, con il server senza più RAM:

In ogni caso la connessione viene chiusa in modo pulito con il close code 1009 di WebSocket (Message Too Big), e la memoria del server non supera mai il tetto fissato.

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;

Analisi sicura della lunghezza dei frame

I frame WebSocket possono contenere un campo di lunghezza a 64-bit. Secondo RFC 6455 il bit più significativo di quel campo deve essere zero. sgcWebSockets ora rifiuta un frame la cui lunghezza a 64-bit ha il bit più alto impostato, invece di fidarsene, così il limite di dimensione descritto sopra non può essere aggirato con un intero che va in overflow. Questo controllo è sempre attivo e non dipende da MaxMessageSize.

Handshake più rigorosi

Due nuove opzioni sotto SecurityOptions rafforzano l’upgrade WebSocket stesso, e sono entrambe abilitate per impostazione predefinita.

EnforceWebSocketVersion risponde a qualunque handshake che richieda una versione diversa dalla 13 con un 426 Upgrade Required e un header Sec-WebSocket-Version: 13, invece di completare l’upgrade. ValidateWebSocketKey rifiuta, con un 400 Bad Request, qualunque handshake il cui Sec-WebSocket-Key sia assente o non sia un nonce base64 valido di 16 byte. Entrambi i controlli si applicano solo al percorso RFC 6455, quindi i client più vecchi basati su specifiche legacy non ne risentono.

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;

Come si integra con il firewall

Queste protezioni risiedono nel livello di protocollo, all’interno del parser dei frame, che è esattamente il punto in cui avvengono gli attacchi alla memoria. È la parte che i componenti Firewall e RateLimiter non possono raggiungere, perché vedono un messaggio solo dopo che è stato decodificato. I due livelli si completano a vicenda: continua a usare il firewall e il rate limiter per il filtraggio degli IP, i limiti sul rate di connessioni e messaggi e le politiche di origine, e lascia che i nuovi limiti integrati proteggano il parser stesso. Per un server pubblico consigliamo di impostare MaxMessageSize al tuo valore massimo reale, di bloccare OriginsAllowed sul tuo front end e di limitare MaxConnections.

Aggiornamento

Le nuove protezioni sono attive non appena aggiorni, con valori predefiniti sicuri, quindi la maggior parte dei server ottiene il rafforzamento della memoria e dell’handshake senza una singola modifica al codice. Se la tua applicazione scambia legittimamente messaggi più grandi di 64 MB, aumenta MaxMessageSize di conseguenza. Il codice client esistente non ne risente.

Aggiorna dalla pagina di download di sgcWebSockets, oppure ottienilo tramite GetIt o il tuo account registrato.

Domande, feedback o aiuto per la migrazione? Contattaci, riceverai una risposta dalle persone che hanno scritto il codice.